diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7b2f5ed..3713d33 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,7 +26,7 @@ jobs: echo "version=${base_version}-git${build_number}" >> "$GITHUB_OUTPUT" build: - name: sm${{ matrix.sm.label }}-${{ matrix.target.os_name }}-${{ matrix.target.arch }} + name: sm${{ matrix.sm.label }} needs: version runs-on: ${{ matrix.target.os }} container: ${{ matrix.target.container }} @@ -34,27 +34,11 @@ jobs: fail-fast: false matrix: sm: - - label: "1.12" - branch: "1.12-dev" - label: "1.13" - branch: "master" target: - os: ubuntu-latest os_name: linux - arch: x86 container: ghcr.io/alliedmodders/build-containers/debian11-clang22:latest - - os: ubuntu-latest - os_name: linux - arch: x86_64 - container: ghcr.io/alliedmodders/build-containers/debian11-clang22:latest - - os: windows-latest - os_name: windows - arch: x86 - msvc_arch: x86 - - os: windows-latest - os_name: windows - arch: x86_64 - msvc_arch: amd64 steps: - name: Checkout @@ -62,57 +46,7 @@ jobs: with: submodules: recursive - - name: Setup Python (Windows) - if: matrix.target.os_name == 'windows' - uses: actions/setup-python@v7 - with: - python-version: '3.14' - - - name: Setup MSVC (Windows) - if: matrix.target.os_name == 'windows' - uses: ilammy/msvc-dev-cmd@v1 - with: - arch: ${{ matrix.target.msvc_arch }} - - - name: Install AMBuild - if: matrix.target.os_name == 'windows' - shell: bash - run: python -m pip install --upgrade git+https://github.com/alliedmodders/ambuild.git - - - name: Fetch SourceMod - uses: actions/checkout@v7 - with: - repository: alliedmodders/sourcemod - ref: ${{ matrix.sm.branch }} - path: sourcemod - submodules: recursive - - - name: Fetch Metamod:Source - uses: actions/checkout@v7 - with: - repository: alliedmodders/metamod-source - ref: 1.12-dev - path: mmsource - submodules: recursive - - - name: Fetch CSS HL2SDK - uses: actions/checkout@v7 - with: - repository: alliedmodders/hl2sdk - ref: css - path: hl2sdk-css - submodules: recursive - - - name: Fetch CSGO HL2SDK - uses: actions/checkout@v7 - with: - repository: alliedmodders/hl2sdk - ref: csgo - path: hl2sdk-csgo - submodules: recursive - - - name: Fetch SourceMod Binary (Linux) - if: matrix.target.os_name == 'linux' + - name: Fetch SourceMod Binary run: | mkdir sm_bin wget -O sm_bin.tar.gz "https://www.sourcemod.net/latest.php?os=linux&version=${{ matrix.sm.label }}" @@ -121,59 +55,21 @@ jobs: cd .. rm sm_bin.tar.gz - - name: Fetch SourceMod Binary (Windows) - if: matrix.target.os_name == 'windows' - run: | - Invoke-WebRequest -OutFile sm_bin.zip -Uri "https://www.sourcemod.net/latest.php?os=windows&version=${{ matrix.sm.label }}" - Expand-Archive -Path sm_bin.zip -DestinationPath sm_bin - Remove-Item -Path sm_bin.zip - - - name: Set environment variables (Linux) - if: matrix.target.os_name == 'linux' + - name: Set environment variables run: | - echo "SOURCEMOD=$GITHUB_WORKSPACE/sourcemod" >> $GITHUB_ENV echo "SOURCEMOD_BIN=$GITHUB_WORKSPACE/sm_bin" >> $GITHUB_ENV - echo "MMSOURCE=$GITHUB_WORKSPACE/mmsource" >> $GITHUB_ENV - echo "HL2SDKCSS=$GITHUB_WORKSPACE/hl2sdk-css" >> $GITHUB_ENV - echo "HL2SDKCSGO=$GITHUB_WORKSPACE/hl2sdk-csgo" >> $GITHUB_ENV - - - name: Set environment variables (Windows) - if: matrix.target.os_name == 'windows' - run: | - echo "SOURCEMOD=$env:GITHUB_WORKSPACE/sourcemod" >> $env:GITHUB_ENV - echo "SOURCEMOD_BIN=$env:GITHUB_WORKSPACE/sm_bin" >> $env:GITHUB_ENV - echo "MMSOURCE=$env:GITHUB_WORKSPACE/mmsource" >> $env:GITHUB_ENV - echo "HL2SDKCSS=$env:GITHUB_WORKSPACE/hl2sdk-css" >> $env:GITHUB_ENV - echo "HL2SDKCSGO=$env:GITHUB_WORKSPACE/hl2sdk-csgo" >> $env:GITHUB_ENV - - name: Build (Linux) - if: matrix.target.os_name == 'linux' - env: - CC: clang-22 - CXX: clang++-22 + - name: Build run: | python3 ./configure.py \ - -o build \ - --targets ${{ matrix.target.arch }} \ - --enable-optimize - cd build - ambuild - - - name: Build (Windows) - if: matrix.target.os_name == 'windows' - shell: bash - run: | - python ./configure.py \ - -o build \ - --targets ${{ matrix.target.arch }} \ - --enable-optimize + -o build cd build ambuild - name: Upload package artifact uses: actions/upload-artifact@v7 with: - name: pkg-sm${{ matrix.sm.label }}-${{ matrix.target.os_name }}-${{ matrix.target.arch }} + name: pkg-sm${{ matrix.sm.label }} path: build/package if-no-files-found: error @@ -201,34 +97,18 @@ jobs: version="${{ needs.version.outputs.version }}" echo "version=${version}" >> "$GITHUB_OUTPUT" - # One package per SourceMod version per OS: Windows as .zip, Linux as - # .tar.gz. Each merges that combination's per-arch slices (the include - # file rides along in every slice). assets="" for label in 1.12 1.13; do - for os_name in windows linux; do - dest="package-sm${label}-${os_name}/" - mkdir -p "${dest}" - for dir in artifacts/pkg-sm${label}-${os_name}-*/; do - cp -a "${dir}." "${dest}/" - [ -d "${dest}/cfg/cssdm/maps" ] || mkdir -p "${dest}/cfg/cssdm/maps" - done - if [ "${os_name}" = "windows" ]; then - asset="cssdm-${version}-sm${label}-windows.zip" - (cd "package-sm${label}-${os_name}" && zip -r "../${asset}" *) - else - # fix permissions of the dlls first - pushd "package-sm${label}-${os_name}"/addons/sourcemod/extensions - chmod +x *.so - pushd x64 - chmod +x *.so - popd - popd - asset="cssdm-${version}-sm${label}-linux.tar.gz" - (cd "package-sm${label}-${os_name}" && tar -czf "../${asset}" .) - fi - assets="${assets} ${asset}" + dest="package-sm${label}/" + mkdir -p "${dest}" + for dir in artifacts/pkg-sm${label}/; do + cp -a "${dir}." "${dest}/" + [ -d "${dest}/cfg/cssdm/maps" ] || mkdir -p "${dest}/cfg/cssdm/maps" done + asset="cssdm-${version}-sm${label}.zip" + (cd "package-sm${label}" && zip -r "../${asset}" *) + fi + assets="${assets} ${asset}" done echo "assets=${assets# }" >> "$GITHUB_OUTPUT" diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 8492a05..0000000 --- a/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "hl2sdk-manifests"] - path = hl2sdk-manifests - url = https://github.com/alliedmodders/hl2sdk-manifests/ diff --git a/AMBuildScript b/AMBuildScript index 1d81797..50f33b3 100644 --- a/AMBuildScript +++ b/AMBuildScript @@ -23,410 +23,11 @@ def ResolveEnvPath(env, folder): def Normalize(path): return os.path.abspath(os.path.normpath(path)) -def SetArchFlags(compiler): - if compiler.behavior == 'gcc': - if compiler.target.arch == 'x86_64': - compiler.cflags += ['-fPIC'] - elif compiler.like('msvc'): - if compiler.target.arch == 'x86_64': - compiler.defines += ['WIN64'] - -hl2sdk_manifests_path = None - -# First we check if the manifest exists in the current path -hl2sdk_manifests_path = os.path.join(builder.sourcePath, 'hl2sdk-manifests', 'SdkHelpers.ambuild') - -if not os.path.exists(hl2sdk_manifests_path): - # manifests does not exists in the project file, use the path from --hl2sdk-manifest-path - if not builder.options.hl2sdk_manifest: - raise Exception('HL2SDK Manifest root path not set! (--hl2sdk-manifest-path)') - else: - hl2sdk_manifests_path = os.path.join(builder.options.hl2sdk_manifest, 'SdkHelpers.ambuild') - - if not os.path.exists(hl2sdk_manifests_path): - raise Exception('Could not find SdkHelpers.ambuild in the given HL2SDK Manifest path!') - - -SdkHelpers = builder.Eval(hl2sdk_manifests_path, { - 'Project': 'cssdm' -}) - class ExtensionConfig(object): def __init__(self): - self.sdk_manifests = [] - self.sdks = {} - self.sdk_targets = [] - self.extensions = [] - self.plugins = {} - self.generated_headers = None - self.mms_root = None - self.sm_root = None self.sm_bin_root = None self.spcomp = None - self.all_targets = [] - self.target_archs = set() - - if builder.options.targets: - target_archs = builder.options.targets.split(',') - else: - target_archs = ['x86', '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(f'Skipping target {arch}: {e}') - continue - self.all_targets.append(cxx) - - if not self.all_targets: - raise Exception('No suitable C/C++ compiler was found.') - - def use_auto_versioning(self): - if builder.backend != 'amb2': - return False - return not getattr(builder.options, 'disable_auto_versioning', False) - - @property - def tag(self): - if builder.options.debug == '1': - return 'Debug' - return 'Release' - - @staticmethod - def findSdkPath(sdk_name): - dir_name = f'hl2sdk-{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(f'HL2SDK{sdk_name.upper()}', dir_name) - - @staticmethod - def shouldIncludeSdk(sdk): - return sdk['name'] in ['css', 'csgo'] - - def detectSDKs(self): - sdk_list = [s for s in builder.options.sdks.split(',') if s] - SdkHelpers.sdk_filter = ExtensionConfig.shouldIncludeSdk - SdkHelpers.find_sdk_path = ExtensionConfig.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 - - if builder.options.mms_path: - self.mms_root = builder.options.mms_path - else: - self.mms_root = ResolveEnvPath('MMSOURCE112', 'mmsource-1.12') - if not self.mms_root: - self.mms_root = ResolveEnvPath('MMSOURCE', 'metamod-source') - if not self.mms_root: - self.mms_root = ResolveEnvPath('MMSOURCE_DEV', 'metamod-source') - if not self.mms_root: - self.mms_root = ResolveEnvPath('MMSOURCE_DEV', 'mmsource-central') - - if not self.mms_root or not os.path.isdir(self.mms_root): - raise Exception('Could not find a source copy of Metamod:Source') - self.mms_root = Normalize(self.mms_root) - - if builder.options.sm_path: - self.sm_root = builder.options.sm_path - else: - self.sm_root = ResolveEnvPath('SOURCEMOD112', 'sourcemod-1.12') - if not self.sm_root: - self.sm_root = ResolveEnvPath('SOURCEMOD', 'sourcemod') - if not self.sm_root: - self.sm_root = ResolveEnvPath('SOURCEMOD_DEV', 'sourcemod') - if not self.sm_root: - self.sm_root = ResolveEnvPath('SOURCEMOD_DEV', 'sourcemod-central') - - if not self.sm_root or not os.path.isdir(self.sm_root): - raise Exception('Could not find a source copy of SourceMod') - self.sm_root = Normalize(self.sm_root) - - def configure(self): - allowed_archs = ['x86', 'x86_64'] - - if not set(self.target_archs).issubset(allowed_archs): - raise Exception(f'Unknown target architecture: {self.target_archs}') - - for cxx in self.all_targets: - self.configure_cxx(cxx) - - def configure_cxx(self, cxx): - if cxx.family == 'msvc': - if cxx.version < 1914 and builder.options.generator != 'vs': - raise Exception(f'Only MSVC 2017 15.7 and later are supported, full C++17 support is required. ({str(cxx.version)} < 1914)') - elif cxx.family == 'gcc': - if cxx.version < 'gcc-8': - raise Exception('Only GCC versions 8 or later are supported, full C++17 support is required.') - elif cxx.family == 'clang': - if cxx.version < 'clang-5': - raise Exception('Only clang versions 5 or later are supported, full C++17 support is required.') - - if cxx.like('gcc'): - self.configure_gcc(cxx) - elif cxx.family == 'msvc': - self.configure_msvc(cxx) - - # Optimization - if builder.options.opt == '1': - cxx.defines += ['NDEBUG'] - - # Debugging - if builder.options.debug == '1': - cxx.defines += ['DEBUG', '_DEBUG'] - - # Platform-specifics - if cxx.target.platform == 'linux': - self.configure_linux(cxx) - elif cxx.target.platform == 'mac': - self.configure_mac(cxx) - elif cxx.target.platform == 'windows': - self.configure_windows(cxx) - - def configure_gcc(self, cxx): - 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-invalid-offsetof', - '-Wno-unused', - '-Wno-switch', - '-fvisibility=hidden', - ] - - if cxx.target.arch in ['x86', 'x86_64']: - cxx.cflags += ['-msse'] - - cxx.cxxflags += [ - '-fno-exceptions', - '-fno-rtti', - '-fno-threadsafe-statics', - '-Wno-delete-non-virtual-dtor', - '-Wno-non-virtual-dtor', - '-Wno-overloaded-virtual', - '-Wno-register', - '-fvisibility-inlines-hidden', - '-std=c++20', - ] - - have_gcc = cxx.family == 'gcc' - have_clang = cxx.family == 'clang' - - # Work around errors from smsdk_ext.cpp - if have_clang: - cxx.cxxflags += ['-Wno-implicit-exception-spec-mismatch'] - - # 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', - ] - - # C++20 deprecates volatile ++/-- and compound assignment (P1152R4). - if cxx.version >= 'clang-12.0' or cxx.version >= 'apple-clang-13.0': - cxx.cxxflags += ['-Wno-deprecated-volatile'] - - if have_gcc: - cxx.cflags += ['-mfpmath=sse'] - cxx.cflags += ['-Wno-maybe-uninitialized'] - - if builder.options.opt == '1': - cxx.cflags += ['-O3'] - - # Don't omit the frame pointer. - cxx.cflags += ['-fno-omit-frame-pointer'] - - def configure_msvc(self, cxx): - 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', - '_ITERATOR_DEBUG_LEVEL=0', - ] - cxx.cflags += [ - '/W3', - '/Zi' - ] - cxx.cxxflags += [ - '/EHsc', - '/GR-', - '/TP', - '/std:c++20', - ] - cxx.linkflags += [ - 'kernel32.lib', - 'user32.lib', - 'gdi32.lib', - 'winspool.lib', - 'comdlg32.lib', - 'advapi32.lib', - 'shell32.lib', - 'ole32.lib', - 'oleaut32.lib', - 'uuid.lib', - 'odbc32.lib', - 'odbccp32.lib', - 'legacy_stdio_definitions.lib' - ] - - if builder.options.opt == '1': - cxx.cflags += ['/Ox', '/Zo'] - cxx.linkflags += ['/OPT:ICF', '/OPT:REF'] - - if builder.options.debug == '1': - cxx.cflags += ['/Od', '/RTC1'] - - # This needs to be after our optimization flags which could otherwise disable it. - # Don't omit the frame pointer. - cxx.cflags += ['/Oy-'] - - def configure_linux(self, cxx): - cxx.defines += ['LINUX', '_LINUX', 'POSIX', '_FILE_OFFSET_BITS=64'] - cxx.linkflags += ['-lm'] - if cxx.family == 'gcc': - cxx.linkflags += ['-static-libgcc'] - elif cxx.family == 'clang': - cxx.linkflags += ['-lgcc_eh'] - cxx.linkflags += ['-static-libstdc++'] - - def configure_mac(self, cxx): - cxx.defines += ['OSX', '_OSX', 'POSIX', 'KE_ABSOLUTELY_NO_STL'] - cxx.cflags += ['-mmacosx-version-min=10.15'] - cxx.linkflags += [ - '-mmacosx-version-min=10.15', - '-stdlib=libc++', - '-lc++', - ] - cxx.cxxflags += ['-stdlib=libc++'] - - def configure_windows(self, cxx): - cxx.defines += ['WIN32', '_WINDOWS'] - - def LibraryBuilder(self, compiler, name): - binary = compiler.Library(name) - self.AddVersioning(binary) - if binary.compiler.like('msvc'): - binary.compiler.linkflags += ['/SUBSYSTEM:WINDOWS'] - self.AddCxxCompat(binary) - return binary - - def Library(self, context, compiler, name): - compiler = compiler.clone() - SetArchFlags(compiler) - return self.LibraryBuilder(compiler, name) - - def ConfigureForExtension(self, context, compiler): - compiler.cxxincludes += [ - os.path.join(context.currentSourcePath), - os.path.join(context.currentSourcePath, 'sdk'), - os.path.join(self.sm_root, 'public'), - os.path.join(self.sm_root, 'public', 'extensions'), - os.path.join(self.sm_root, 'sourcepawn', 'include'), - os.path.join(self.sm_root, 'public', 'amtl', 'amtl'), - os.path.join(self.sm_root, 'public', 'amtl'), - ] - return compiler - - def ExtLibrary(self, context, compiler, name): - binary = self.Library(context, compiler, name) - SetArchFlags(compiler) - self.ConfigureForExtension(context, binary.compiler) - return binary - - def AddCxxCompat(self, binary): - if binary.compiler.target.platform == 'linux': - binary.sources += [ - os.path.join(self.sm_root, 'public', 'amtl', 'compat', 'stdcxx.cpp'), - ] - - @staticmethod - def binary_output_name(binary, binary_type): - target = binary.compiler.target - if binary_type == 'program': - name_fn = binary.compiler.vendor.nameForExecutable - elif binary_type == 'library': - name_fn = binary.compiler.vendor.nameForSharedLibrary - else: - raise Exception('Unsupported binary type: {}'.format(binary_type)) - - try: - return name_fn(binary.name_, target) - except TypeError: - # Older AMBuild versions did not require the target argument. - return name_fn(binary.name_) - - def auto_version(self, binary): - if not self.use_auto_versioning(): - return - binary.compiler.defines += [ - 'CSSDM_GENERATED_BUILD' - ] - if binary.compiler.target.platform == 'windows': - binary.sources += ['version.rc'] - binary.compiler.rcdefines += [ - 'BINARY_NAME="{0}"'.format(ExtensionConfig.binary_output_name(binary, 'library')), - 'RC_COMPILE' - ] - - binary.compiler.cxxincludes += [os.path.join(builder.buildPath, 'includes')] - binary.compiler.sourcedeps += self.generated_headers - - def ConfigureForHL2(self, context, binary, sdk): - compiler = binary.compiler - SetArchFlags(compiler) - - compiler.cxxincludes += [ - os.path.join(self.mms_root, 'core'), - os.path.join(self.mms_root, 'core', 'sourcehook'), - ] - - for other_sdk in self.sdk_manifests: - compiler.defines += [f'SE_{other_sdk["define"]}={other_sdk["code"]}'] - - SdkHelpers.configureCxx(context, binary, sdk) - - return binary - - def HL2Library(self, context, compiler, name, sdk): - binary = self.Library(context, compiler, name) - self.ConfigureForExtension(context, binary.compiler) - return self.ConfigureForHL2(context, binary, sdk) - - def HL2Config(self, project, context, compiler, name, sdk): - binary = project.Configure(compiler, name, f'{self.tag} - {sdk["name"]} {compiler.target.arch}') - self.AddCxxCompat(binary) - return self.ConfigureForHL2(context, binary, sdk) - - def HL2ExtConfig(self, project, context, compiler, name, sdk): - binary = project.Configure(compiler, name, f'{self.tag} - {sdk["name"]} {compiler.target.arch}') - self.AddCxxCompat(binary) - self.ConfigureForHL2(context, binary, sdk) - self.ConfigureForExtension(context, binary.compiler) - return binary + self.plugins = {} def find_spcomp(self): exe_suffix = "" if not os.name == "nt" else ".exe" @@ -448,21 +49,9 @@ class ExtensionConfig(object): raise Exception("Could not find a suitable copy of spcomp in SourceMod binary root") Extension = ExtensionConfig() -Extension.detectSDKs() Extension.find_spcomp() -Extension.configure() - -Extension.generated_headers = builder.Build( - 'buildbot/Versioning', - { 'CSSDM': Extension } -) - -# This will clone the list and each cxx object as we recurse, preventing child -# scripts from messing up global state. -builder.targets = builder.CloneableList(Extension.all_targets) BuildScripts = [ - 'AMBuilder', 'scripting/AMBuilder', 'PackageScript', ] diff --git a/AMBuilder b/AMBuilder deleted file mode 100644 index 68375e6..0000000 --- a/AMBuilder +++ /dev/null @@ -1,36 +0,0 @@ -# vim: set ts=2 sw=2 tw=99 noet ft=python: -import os - -projectName = 'cssdm' - -sourceFiles = [ - 'cssdm_main.cpp', - 'cssdm_config.cpp', - 'cssdm_callbacks.cpp', - 'cssdm_ctrl.cpp', - 'cssdm_events.cpp', - 'cssdm_weapons.cpp', - 'cssdm_players.cpp', - 'cssdm_ffa.cpp', - 'cssdm_utils.cpp', -] - -project = builder.LibraryProject(projectName) - -if os.path.isfile(os.path.join(builder.currentSourcePath, 'sdk', 'smsdk_ext.cpp')): - project.sources += [os.path.join('sdk', 'smsdk_ext.cpp')] -else: - project.sources += [os.path.join(Extension.sm_root, 'public', 'smsdk_ext.cpp')] - -project.sources += sourceFiles - -for sdk_target in Extension.sdk_targets: - sdk = sdk_target.sdk - cxx = sdk_target.cxx - if sdk['name'] in ['mock']: - continue - - binary = Extension.HL2ExtConfig(project, builder, cxx, projectName + '.ext.' + sdk['extension'], sdk) - Extension.auto_version(binary) - -Extension.extensions += builder.Add(project) diff --git a/PackageScript b/PackageScript index d7c45b5..12fc807 100644 --- a/PackageScript +++ b/PackageScript @@ -10,8 +10,6 @@ folder_list = [ 'cfg/cssdm/spawns', 'cfg/cssdm/spawns/cstrike', 'cfg/cssdm/spawns/csgo', - 'addons/sourcemod/extensions', - 'addons/sourcemod/extensions/x64', 'addons/sourcemod/plugins', 'addons/sourcemod/plugins/cssdm', 'addons/sourcemod/scripting', @@ -20,11 +18,6 @@ folder_list = [ 'addons/sourcemod/translations' ] -if 'x86_64' in Extension.target_archs: - folder_list.extend([ - 'addons/sourcemod/extensions/x64', - ]) - # Create the distribution folder hierarchy. folder_map = {} for folder in folder_list: @@ -58,6 +51,7 @@ CopyFiles('scripting/include', 'addons/sourcemod/scripting/include', [ # Script sources CopyFiles('scripting', 'addons/sourcemod/scripting', [ + 'dm_base.sp', 'dm_basics.sp', 'dm_bot_quotas.sp', 'dm_equipment.sp', @@ -96,13 +90,6 @@ for entry in os.listdir(base_translations_dir): folder_map[dest_entry] = builder.AddFolder(dest_entry) CopyDirectory(os.path.join('translations', entry), dest_entry) -# Copy binaries. -for cxx_task in Extension.extensions: - if cxx_task.target.arch == 'x86_64': - builder.AddCopy(cxx_task.binary, folder_map['addons/sourcemod/extensions/x64']) - else: - builder.AddCopy(cxx_task.binary, folder_map['addons/sourcemod/extensions']) - # Copy plugins for smx_file, smx_entry in Extension.plugins.items(): builder.AddCopy(smx_entry, folder_map['addons/sourcemod/plugins/cssdm']) diff --git a/buildbot/Versioning b/buildbot/Versioning deleted file mode 100644 index 5c0485b..0000000 --- a/buildbot/Versioning +++ /dev/null @@ -1,46 +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, 'buildbot', 'generate_headers.py'), - os.path.join(builder.sourcePath), - os.path.join(builder.buildPath, 'includes'), -] - -outputs = [ - os.path.join(builder.buildFolder, 'includes', 'cssdm_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] -] - -output_nodes = builder.AddCommand( - inputs=sources, - argv=argv, - outputs=outputs -) - -rvalue = output_nodes diff --git a/buildbot/bootstrap.pl b/buildbot/bootstrap.pl deleted file mode 100755 index 9174314..0000000 --- a/buildbot/bootstrap.pl +++ /dev/null @@ -1,87 +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; - -#update and configure shiz -if ($^O eq "linux") { - $ENV{'SOURCEMOD110'} = '/home/builds/common/sourcemod-1.10'; -} elsif ($^O eq "darwin") { - $ENV{'SOURCEMOD110'} = '/Users/builds/slaves/common/sourcemod-1.10'; -} else { - #JUST IN CASE - $ENV{'SOURCEMOD110'} = 'D:\\scripts\\common\\sourcemod-1.10'; - #$ENV{'MMSOURCE19'} = "C:\\Scripts\\common\\mmsource-1.9"; - #$ENV{'HL2SDKCSGO'} = "C:\\Scripts\\common\\hl2sdk-csgo"; -} - -#Create output folder if it doesn't exist. -if (!(-d 'OUTPUT')) { - $reconf = 1; -} else { - if (-f 'OUTPUT/sentinel') { - my @s = stat('OUTPUT/sentinel'); - my $mtime = $s[9]; - my @files = ('build/pushbuild.txt', 'build/AMBuildScript', 'build/product.version'); - my ($i); - for ($i = 0; $i <= $#files; $i++) { - if (IsNewer($files[$i], $mtime)) { - $reconf = 1; - last; - } - } - } else { - $reconf = 1; - } -} - -if ($reconf) { - rmtree('OUTPUT'); - mkdir('OUTPUT') or die("Failed to create output folder: $!\n"); - chdir('OUTPUT'); - my ($result); - print "Attempting to reconfigure...\n"; - if ($^O eq "linux") { - $result = `CC=gcc CXX=gcc python3 ../build/configure.py --enable-optimize`; - } elsif ($^O eq "darwin") { - $result = `CC=clang CXX=clang python3 ../build/configure.py --enable-optimize`; - } else { - $result = `C:\\Python31\\Python.exe ..\\build\\configure.py --enable-optimize`; - } - print "$result\n"; - if ($? != 0) { - die('Could not configure!'); - } - open(FILE, '>sentinel'); - print FILE "this is nothing.\n"; - close(FILE); -} - -sub IsNewer -{ - my ($file, $time) = (@_); - - my @s = stat($file); - my $mtime = $s[9]; - return $mtime > $time; -} - -exit(0); - - diff --git a/buildbot/build_type b/buildbot/build_type deleted file mode 100644 index 38f8e88..0000000 --- a/buildbot/build_type +++ /dev/null @@ -1 +0,0 @@ -dev diff --git a/buildbot/generate_headers.py b/buildbot/generate_headers.py deleted file mode 100755 index 8420e18..0000000 --- a/buildbot/generate_headers.py +++ /dev/null @@ -1,58 +0,0 @@ -#!/usr/bin/env python3 -# 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) - -source_dir = os.path.abspath(os.path.normpath(argv[0])) -build_dir = os.path.normpath(argv[1]) - -def GetVersion(): - with open(os.path.join(source_dir, '.git', 'HEAD')) as fp: - head_contents = fp.read().strip() - if re.search(r'^[a-fA-F0-9]{40}$', head_contents): - git_head_path = os.path.join(source_dir, '.git', 'HEAD') - else: - git_state = head_contents.split(':')[1].strip() - git_head_path = os.path.join(source_dir, '.git', git_state) - if not os.path.exists(git_head_path): - git_head_path = os.path.join(source_dir, '.git', 'HEAD') - - return open(git_head_path, 'r').read().strip(); - -def PerformReversioning(): - rev = GetVersion() - - args = ['git', 'rev-list', '--count', 'HEAD'] - cset = subprocess.run(args, capture_output=True, text=True).stdout.strip() - - with open(os.path.join(source_dir, 'product.version'), 'r') as productFile: - productContents = productFile.read() - m = re.match(r'(\d+)\.(\d+)\.(\d+)(.*)', productContents) - if m == None: - raise Exception('Could not detremine product version') - major, minor, release, tag = m.groups() - - if not os.path.isdir(build_dir): - os.makedirs(build_dir) - incFile = open(os.path.join(build_dir, 'cssdm_version_auto.h'), 'w') - incFile.write(""" -#ifndef _CSSDM_AUTO_VERSION_INFORMATION_H_ -#define _CSSDM_AUTO_VERSION_INFORMATION_H_ - -#define CSSDM_BUILD_STRING \"{0}\" -#define CSSDM_BUILD_UNIQUEID \"{1}:{2}\" CSSDM_BUILD_STRING -#define CSSDM_FULL_VERSION \"{3}.{4}.{5}\" CSSDM_BUILD_STRING -#define CSSDM_FILE_VERSION {6},{7},{8},0 - -#endif /* _CSSDM_AUTO_VERSION_INFORMATION_H_ */ - -""".format(tag, rev, cset, major, minor, release, major, minor, release)) - incFile.close() - -PerformReversioning() diff --git a/buildbot/helpers.pm b/buildbot/helpers.pm deleted file mode 100644 index 1e3e13e..0000000 --- a/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/buildbot/package.pl b/buildbot/package.pl deleted file mode 100755 index 03e60d0..0000000 --- a/buildbot/package.pl +++ /dev/null @@ -1,93 +0,0 @@ -#!/usr/bin/perl - -use strict; -use Cwd; -use File::Basename; -use Net::FTP; - -my ($ftp_file, $ftp_host, $ftp_user, $ftp_pass, $ftp_path); - -$ftp_file = 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; -} - -my ($filename); -$filename = 'cssdm-' . $version; -if ($^O eq "linux") -{ - $filename .= '.tar.gz'; - print "tar zcvf $filename addons cfg\n"; - system("tar zcvf $filename addons cfg"); -} -else -{ - $filename .= '.zip'; - print "zip -r $filename addons cfg\n"; - system("zip -r $filename addons cfg"); -} - -my ($major,$minor) = ($version =~ /^(\d+)\.(\d+)/); -$ftp_path .= "/cssdm/$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->close(); - -print "File sent to drop site as $filename -- build succeeded.\n"; - -exit(0); - diff --git a/buildbot/startbuild.pl b/buildbot/startbuild.pl deleted file mode 100755 index abe0dd3..0000000 --- a/buildbot/startbuild.pl +++ /dev/null @@ -1,27 +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'); - -if ($^O eq "linux" || $^O eq "darwin") { - system("python3 build.py 2>&1"); -} else { - system("C:\\Python31\\python.exe build.py 2>&1"); -} - -if ($? != 0) -{ - die "Build failed: $!\n"; -} -else -{ - exit(0); -} - diff --git a/buildbot/symstore.pl b/buildbot/symstore.pl deleted file mode 100755 index 7332903..0000000 --- a/buildbot/symstore.pl +++ /dev/null @@ -1,64 +0,0 @@ -#!/usr/bin/perl - -use File::Basename; - -my ($myself, $path) = fileparse($0); -chdir($path); - -require 'helpers.pm'; - -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 .= '-hg' . Build::HgRevNum('.'); - -my ($build_type); -$build_type = Build::GetBuildType(Build::PathFormat('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:\\cssdm\" /t \"Stripper\" /v \"$version\" /c \"$build_type\""); -} - -close(PDBLOG); - -#Lowercase DLLs. Sigh. -my (@files); -opendir(DIR, "S:\\cssdm"); -@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:\\cssdm\\$file"); - opendir(DIR, "S:\\cssdm\\$file"); - @subdirs = readdir(DIR); - closedir(DIR); - for ($j = 0; $j <= $#subdirs; $j++) - { - next unless ($subdirs[$j] =~ /[A-Z]/); - Build::Command("rename S:\\cssdm\\$file\\" . $subdirs[$j] . " " . lc($subdirs[$j])); - } -} - diff --git a/cfg/cssdm.cfg b/cfg/cssdm.cfg index 0e07ee8..0f4fed5 100644 --- a/cfg/cssdm.cfg +++ b/cfg/cssdm.cfg @@ -127,3 +127,9 @@ cssdm_bots_balance "0" // Requires: dm_basics.smx // Default: "1" cssdm_remove_drops "1" + +// Enables the spawn editor. +// -- +// Requires: dm_preset_spawns.smx +// Default: "0" +cssdm_enable_spawn_editor "0" diff --git a/configure.py b/configure.py index 2531908..6599098 100644 --- a/configure.py +++ b/configure.py @@ -5,24 +5,6 @@ # Simple extensions do not need to modify this file. 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('--hl2sdk-manifest-path', type=str, dest='hl2sdk_manifest', default=None, - help='Path to HL2SDK Manifests') -parser.options.add_argument('--sm-path', type=str, dest='sm_path', default=None, - help='Path to SourceMod') parser.options.add_argument('--sm-bin-path', type=str, dest='sm_bin_path', default=None, help='Path to SourceMod (binary copy)') -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.Configure() diff --git a/cssdm_callbacks.cpp b/cssdm_callbacks.cpp deleted file mode 100644 index f209d7a..0000000 --- a/cssdm_callbacks.cpp +++ /dev/null @@ -1,237 +0,0 @@ -/** - * vim: set ts=4 : - * =============================================================== - * CS:S DM, Copyright (C) 2004-2007 AlliedModders LLC. - * By David "BAILOPAN" Anderson - * 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 as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Version: $Id$ - */ - -#include "cssdm_headers.h" -#include "cssdm_callbacks.h" -#include "cssdm_config.h" -#include "cssdm_weapons.h" -#include "cssdm_players.h" -#include "cssdm_utils.h" - -IForward *g_pOnClientDeath = NULL; -IForward *g_pOnClientSpawned = NULL; -IForward *g_pOnClientPostSpawned = NULL; -IForward *g_pOnSetSpawnMethod = NULL; -IForward *g_pOnStartup = NULL; -IForward *g_pOnShutdown = NULL; - -void DM_InitCallbacks() -{ - g_pOnClientDeath = forwards->CreateForward("DM_OnClientDeath", ET_Hook, 1, NULL, Param_Cell); - g_pOnClientSpawned = forwards->CreateForward("DM_OnClientSpawned", ET_Ignore, 1, NULL, Param_Cell); - g_pOnClientPostSpawned = forwards->CreateForward("DM_OnClientPostSpawned", ET_Ignore, 1, NULL, Param_Cell); - g_pOnSetSpawnMethod = forwards->CreateForward("DM_OnSetSpawnMethod", ET_Hook, 1, NULL, Param_String); - g_pOnStartup = forwards->CreateForward("DM_OnStartup", ET_Ignore, 0, NULL); - g_pOnShutdown = forwards->CreateForward("DM_OnShutdown", ET_Ignore, 0, NULL); -} - -void DM_ShutdownCallbacks() -{ - forwards->ReleaseForward(g_pOnClientDeath); - forwards->ReleaseForward(g_pOnClientSpawned); - forwards->ReleaseForward(g_pOnClientPostSpawned); - forwards->ReleaseForward(g_pOnSetSpawnMethod); - forwards->ReleaseForward(g_pOnStartup); - forwards->ReleaseForward(g_pOnShutdown); -} - -bool DM_OnClientDeath(int client) -{ - cell_t res = 0; - g_pOnClientDeath->PushCell(client); - g_pOnClientDeath->Execute(&res); - - return (res == (cell_t)Pl_Continue); -} - -void DM_OnClientSpawned(int client, bool wasDead) -{ - g_pOnClientSpawned->PushCell(client); - g_pOnClientSpawned->Execute(NULL); - g_pOnClientPostSpawned->PushCell(client); - g_pOnClientPostSpawned->Execute(NULL); -} - -void DM_OnSetSpawnMethod(const char *method) -{ - g_pOnSetSpawnMethod->PushString(method); - g_pOnSetSpawnMethod->Execute(NULL); -} - -void DM_OnStartup() -{ - g_pOnStartup->Execute(NULL); -} - -void DM_OnShutdown() -{ - g_pOnShutdown->Execute(NULL); -} - -static cell_t DMN_GetSpawnMethod(IPluginContext *pContext, const cell_t *params) -{ - pContext->StringToLocal(params[1], params[2], DM_GetSpawnMethod()); - return 1; -} - -static cell_t DMN_GetWeaponID(IPluginContext *pContext, const cell_t *params) -{ - char *str; - - pContext->LocalToString(params[1], &str); - auto weapon = DM_FindWeapon(str); - if (weapon == nullptr) - { - return -1; - } - - return weapon->id; -} - -static cell_t DMN_GetWeaponType(IPluginContext *pContext, const cell_t *params) -{ - auto weapon = DM_GetWeapon(params[1]); - - if (weapon == nullptr) - { - return pContext->ThrowNativeError("Invalid CS:S DM weapon id (%d)", params[1]); - } - - return static_cast(weapon->type); -} - -static cell_t DMN_GetWeaponClassname(IPluginContext *pContext, const cell_t *params) -{ - auto weapon = DM_GetWeapon(params[1]); - - if (weapon == nullptr) - { - return pContext->ThrowNativeError("Invalid CS:S DM weapon id (%d)", params[1]); - } - - pContext->StringToLocal(params[2], params[3], weapon->classname.c_str()); - - return 1; -} - -static cell_t DMN_GetWeaponName(IPluginContext *pContext, const cell_t *params) -{ - auto weapon = DM_GetWeapon(params[1]); - - if (weapon == nullptr) - { - return pContext->ThrowNativeError("Invalid CS:S DM weapon id (%d)", params[1]); - } - - pContext->StringToLocal(params[2], params[3], weapon->display.c_str()); - - return 1; -} - -static cell_t DMN_StripBotItems(IPluginContext *pContext, const cell_t *params) -{ - if (params[1] < 1 || params[1] > gpGlobals->maxClients) - { - return pContext->ThrowNativeError("Invalid client index %d", params[1]); - } - - dm_player_t *player = DM_GetPlayer(params[1]); - if (!player->pEntity) - { - return pContext->ThrowNativeError("Client %d is not in game", params[1]); - } - - if (!player->pBot) - { - return pContext->ThrowNativeError("Client %d is not a bot", params[1]); - } - - player->pBot->RemoveAllItems(false); - - return 1; -} - -static cell_t DMN_IsRunning(IPluginContext *pContext, const cell_t *params) -{ - return g_IsRunning ? true : false; -} - -static cell_t DMN_GetSpawnWaitTime(IPluginContext *pContext, const cell_t *params) -{ - float f = DM_GetRespawnWait(); - return sp_ftoc(f); -} - -static cell_t DMN_RespawnClient(IPluginContext *pContext, const cell_t *params) -{ - if (params[1] < 1 || params[1] > gpGlobals->maxClients) - { - return pContext->ThrowNativeError("Invalid client index %d", params[1]); - } - - dm_player_t *player = DM_GetPlayer(params[1]); - if (!player->pEntity) - { - return pContext->ThrowNativeError("Client %d is not in game", params[1]); - } - - player->is_spawned = params[2] ? false : true; - - DM_RespawnPlayer(params[1]); - - return 1; -} - -static cell_t DMN_IsClientAlive(IPluginContext *pContext, const cell_t *params) -{ - if (params[1] < 1 || params[1] > gpGlobals->maxClients) - { - return pContext->ThrowNativeError("Invalid client index %d", params[1]); - } - - dm_player_t *player = DM_GetPlayer(params[1]); - if (!player->pEntity) - { - return pContext->ThrowNativeError("Client %d is not in game", params[1]); - } - - return DM_IsPlayerAlive(params[1]) ? 1 : 0; -} - -sp_nativeinfo_t g_BaseNatives[] = -{ - {"DM_GetSpawnMethod", DMN_GetSpawnMethod}, - {"DM_GetWeaponID", DMN_GetWeaponID}, - {"DM_GetWeaponType", DMN_GetWeaponType}, - {"DM_StripBotItems", DMN_StripBotItems}, - {"DM_GetWeaponClassname", DMN_GetWeaponClassname}, - {"DM_GetWeaponName", DMN_GetWeaponName}, - {"DM_IsRunning", DMN_IsRunning}, - {"DM_GetSpawnWaitTime", DMN_GetSpawnWaitTime}, - {"DM_RespawnClient", DMN_RespawnClient}, - {"DM_IsClientAlive", DMN_IsClientAlive}, - {NULL, NULL}, -}; diff --git a/cssdm_callbacks.h b/cssdm_callbacks.h deleted file mode 100644 index 04afe75..0000000 --- a/cssdm_callbacks.h +++ /dev/null @@ -1,45 +0,0 @@ -/** - * vim: set ts=4 : - * =============================================================== - * CS:S DM, Copyright (C) 2004-2007 AlliedModders LLC. - * By David "BAILOPAN" Anderson - * 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 as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Version: $Id$ - */ - -#ifndef _INCLUDE_CSSDM_CALLBACKS_H_ -#define _INCLUDE_CSSDM_CALLBACKS_H_ - -#include "smsdk_ext.h" - -/* Forwards */ -bool DM_OnClientDeath(int client); -void DM_OnClientSpawned(int client, bool wasDead); -void DM_OnSetSpawnMethod(const char *method); -void DM_OnStartup(); -void DM_OnShutdown(); - -/* Internal API */ -void DM_InitCallbacks(); -void DM_ShutdownCallbacks(); - -extern sp_nativeinfo_t g_BaseNatives[]; - -#endif //_INCLUDE_CSSDM_CALLBACKS_H_ diff --git a/cssdm_config.cpp b/cssdm_config.cpp deleted file mode 100644 index 2dae187..0000000 --- a/cssdm_config.cpp +++ /dev/null @@ -1,135 +0,0 @@ -/** - * vim: set ts=4 : - * =============================================================== - * CS:S DM, Copyright (C) 2004-2007 AlliedModders LLC. - * By David "BAILOPAN" Anderson - * 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 as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Version: $Id$ - */ - -#include "smsdk_ext.h" -#include "cssdm_config.h" -#include "cssdm_ctrl.h" -#include "cssdm_ffa.h" -#include "cssdm_callbacks.h" -#include "cssdm_headers.h" -#include "cssdm_version.h" - -static void ChangeStatus(IConVar *cvar, const char *value, float flOldValue); -static void ChangeFFAStatus(IConVar *cvar, const char *value, float flOldValue); -static void ChangeSpawnStatus(IConVar *cvar, const char *value, float flOldValue); - -ConVar cssdm_ragdoll_time("cssdm_ragdoll_time", "2", 0, "Sets ragdoll stay time", true, 0.0, true, 20.0); -ConVar cssdm_respawn_wait("cssdm_respawn_wait", "0.75", 0, "Sets respawn wait time"); -ConVar cssdm_version("cssdm_version", CSSDM_FULL_VERSION, FCVAR_NOTIFY, "CS:S DM Version"); -ConVar cssdm_enabled("cssdm_enabled", - "1", - FCVAR_NOTIFY, - "Sets whether CS:S DM is enabled", - false, 0.0f, false, 0.0f, - ChangeStatus); -#if SOURCE_ENGINE != SE_CSGO -ConVar cssdm_ffa_enabled("cssdm_ffa_enabled", - "0", - FCVAR_NOTIFY, - "Sets whether Free-For-All mode is enabled", - false, 0.0f, false, 0.0f, - ChangeFFAStatus); -#endif -ConVar cssdm_spawn_method("cssdm_spawn_method", - "preset", - 0, - "Sets how and where players are spawned", - false, 0.0f, false, 0.0f, - ChangeSpawnStatus); - -class LinkConVars : public IConCommandBaseAccessor -{ -public: - bool RegisterConCommandBase(ConCommandBase *pBase) override - { - return META_REGCVAR(pBase); - } -} s_LinkConVars; - -void SM_InitConCommandBase() -{ - g_pCVar = icvar; - ConVar_Register(0, &s_LinkConVars); -} - -static void ChangeStatus(IConVar *cvar, const char *value, float flOldValue) -{ - if (cssdm_enabled.GetInt()) - { - DM_Enable(); - } else { - DM_Disable(); - } -} - -#if SOURCE_ENGINE != SE_CSGO -static void ChangeFFAStatus(IConVar *cvar, const char *value, float flOldValue) -{ - if (cssdm_ffa_enabled.GetInt() && !DM_FFA_IsPatched() && DM_FFA_IsPrepared()) - { - DM_Patch_FFA(); - } else if (!cssdm_ffa_enabled.GetInt() && DM_FFA_IsPatched()) { - DM_Unpatch_FFA(); - } -} -#endif - -static void ChangeSpawnStatus(IConVar *cvar, const char *value, float flOldValue) -{ - if (strcmp(value, cssdm_spawn_method.GetString()) == 0) - { - return; - } - - DM_OnSetSpawnMethod(cssdm_spawn_method.GetString()); -} - -const char *DM_GetSpawnMethod() -{ - return cssdm_spawn_method.GetString(); -} - -unsigned int DM_GetBodyStayTime() -{ - return cssdm_ragdoll_time.GetInt(); -} - -float DM_GetRespawnWait() -{ - return cssdm_respawn_wait.GetFloat(); -} - -bool DM_IsEnabled() -{ - return (cssdm_enabled.GetInt() != 0); -} - -#if SOURCE_ENGINE != SE_CSGO -bool DM_IsFFAEnabled() -{ - return (cssdm_ffa_enabled.GetInt() != 0); -} -#endif diff --git a/cssdm_config.h b/cssdm_config.h deleted file mode 100644 index d9bbf99..0000000 --- a/cssdm_config.h +++ /dev/null @@ -1,42 +0,0 @@ -/** - * vim: set ts=4 : - * =============================================================== - * CS:S DM, Copyright (C) 2004-2007 AlliedModders LLC. - * By David "BAILOPAN" Anderson - * 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 as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Version: $Id$ - */ - -#ifndef _INCLUDE_CSSDM_CONFIG_H_ -#define _INCLUDE_CSSDM_CONFIG_H_ - -/* External API */ -unsigned int DM_GetBodyStayTime(); -float DM_GetRespawnWait(); -bool DM_IsEnabled(); -#if SOURCE_ENGINE != SE_CSGO -bool DM_IsFFAEnabled(); -#endif -const char *DM_GetSpawnMethod(); - -/* Internal API */ -void SM_InitConCommandBase(); - -#endif //_INCLUDE_CSSDM_CONFIG_H_ diff --git a/cssdm_ctrl.cpp b/cssdm_ctrl.cpp deleted file mode 100644 index 5f76fbd..0000000 --- a/cssdm_ctrl.cpp +++ /dev/null @@ -1,173 +0,0 @@ -/** - * vim: set ts=4 : - * =============================================================== - * CS:S DM, Copyright (C) 2004-2007 AlliedModders LLC. - * By David "BAILOPAN" Anderson - * 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 as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Version: $Id$ - */ - -#include -#include -#include "cssdm_headers.h" -#include "cssdm_config.h" -#include "cssdm_ctrl.h" -#include "cssdm_ffa.h" -#include "cssdm_callbacks.h" -#include "cssdm_events.h" - -extern ConVar cssdm_enabled; -extern ConVar cssdm_ffa_enabled; -extern bool g_IsLoadedOkay; - -bool g_IsRunning = false; -bool g_IsMapStarted = false; -bool g_HasConfigRan = false; - -#if SOURCE_ENGINE == SE_CSGO -// CHalfLife2::GetMapDisplayName in SM -void GetMapDisplayName(const char* mapName, char* mapDisplay, size_t maxLen) -{ -#if WIN32 - strcpy_s(mapDisplay, maxLen, mapName); -#else - snprintf(mapDisplay, maxLen, "%s", mapName); -#endif - - char* pos; - if ((pos = strrchr(mapDisplay, '/')) != NULL || (pos = strrchr(mapDisplay, '\\')) != NULL) - { -#if WIN32 - strcpy_s(mapDisplay, maxLen, &pos[1]); -#else - snprintf(mapDisplay, maxLen, "%s", &pos[1]); -#endif - } - - if ((pos = strstr(mapDisplay, ".ugc")) != NULL) - { - pos[0] = '\0'; - } -} -#endif - -void DM_StartEverything() -{ - if (!g_IsMapStarted || g_HasConfigRan) - { - return; - } - - g_HasConfigRan = true; - - /* If we're not running but we should be, start up now. - * g_IsRunning should never be true here. - */ - if (!g_IsRunning && cssdm_enabled.GetInt() == 1) - { - /* We should be enabled! */ - DM_Enable(); - } -} - -void OnLevelInitialized() -{ - if (!g_IsLoadedOkay) - { - return; - } - - g_IsMapStarted = true; - engine->ServerCommand("exec cssdm/cssdm.cfg\n"); - - char map_cmd[128]; -#if SOURCE_ENGINE == SE_CSGO - char mapDisplay[128]; - GetMapDisplayName(STRING(gpGlobals->mapname), mapDisplay, sizeof(mapDisplay)); - snprintf(map_cmd, sizeof(map_cmd), "exec cssdm/maps/%s.cssdm.cfg\n", mapDisplay); -#else - snprintf(map_cmd, sizeof(map_cmd), "exec cssdm/maps/%s.cssdm.cfg\n", STRING(gpGlobals->mapname)); -#endif - engine->ServerCommand(map_cmd); - - DM_StartEverything(); -} - -void OnLevelEnd() -{ - /* We fully disable CS:S DM when the map ends. - * This is so our DM_Enable call is properly paired, but - * also so CGameRules hooks get flushed. - */ - DM_ClearRagdollTimers(); - if (g_IsRunning) - { - DM_Disable(); - } - - g_IsMapStarted = false; - g_HasConfigRan = false; -} - -bool DM_Disable() -{ - if (!g_IsLoadedOkay || !g_IsRunning) - { - return false; - } - - g_IsRunning = false; - -#if SOURCE_ENGINE != SE_CSGO - /* If FFA is enabled, we must unpatch it. */ - if (DM_FFA_IsPatched()) - { - DM_Unpatch_FFA(); - } -#endif - - DM_OnShutdown(); - - return true; -} - -bool DM_Enable() -{ - if (!g_IsLoadedOkay || g_IsRunning || !g_IsMapStarted || !g_HasConfigRan) - { - return false; - } - - g_IsRunning = true; - - DM_OnStartup(); - -#if SOURCE_ENGINE != SE_CSGO - /* If FFA should be enabled, patch it. */ - if (cssdm_ffa_enabled.GetInt() != 0 - && DM_FFA_IsPrepared() - && !DM_FFA_IsPatched()) - { - DM_Patch_FFA(); - } -#endif - - return true; -} diff --git a/cssdm_ctrl.h b/cssdm_ctrl.h deleted file mode 100644 index a4c5286..0000000 --- a/cssdm_ctrl.h +++ /dev/null @@ -1,38 +0,0 @@ -/** - * vim: set ts=4 : - * =============================================================== - * CS:S DM, Copyright (C) 2004-2007 AlliedModders LLC. - * By David "BAILOPAN" Anderson - * 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 as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Version: $Id$ - */ - -#ifndef _INCLUDE_CSSDM_CTRL_H_ -#define _INCLUDE_CSSDM_CTRL_H_ - -/** API */ -bool DM_Disable(); -bool DM_Enable(); - -/** Internal callbacks */ -void OnLevelInitialized(); -void OnLevelEnd(); - -#endif //_INCLUDE_CSSDM_CTRL_H_ diff --git a/cssdm_events.cpp b/cssdm_events.cpp deleted file mode 100644 index 8561cd8..0000000 --- a/cssdm_events.cpp +++ /dev/null @@ -1,346 +0,0 @@ -/** - * vim: set ts=4 : - * =============================================================== - * CS:S DM, Copyright (C) 2004-2007 AlliedModders LLC. - * By David "BAILOPAN" Anderson - * 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 as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Version: $Id$ - */ - -#include - -#include "cssdm_events.h" -#include "cssdm_players.h" -#include "cssdm_utils.h" -#include "cssdm_config.h" -#include "cssdm_headers.h" -#include "cssdm_callbacks.h" -#include "cssdm_weapons.h" - -// TODO : Fix passing clients around in timers - -bool g_InRoundRestart = false; -std::list g_RagdollTimers; - -class RagdollRemoval : public ITimedEvent -{ -public: - ResultType OnTimer(ITimer *pTimer, void *pData) override - { - if (g_IsRunning) - { - DMData *data = static_cast(pData); - int index = data->index; - int serial = data->serial; - - edict_t *pEdict = gamehelpers->EdictOfIndex(index); - if (pEdict && !pEdict->IsFree() && DM_CheckSerial(pEdict, serial)) - { - CBaseEntity *pEntity = DM_GetBaseEntity(index); - if (pEntity) - { - DM_RemoveEntity(pEntity); - } - } - } - g_RagdollTimers.remove(pTimer); - - return Pl_Stop; - } - - void OnTimerEnd(ITimer *pTimer, void *pData) override - { - delete static_cast(pData); - } -} s_RagdollRemover; - -class PlayerSpawner : public ITimedEvent -{ -public: - ResultType OnTimer(ITimer *pTimer, void *pData) override - { - if (!g_IsRunning) - { - return Pl_Stop; - } - - /* Read pack data */ - DMData *data = static_cast(pData); - int client = data->index; - - dm_player_t *player = DM_GetPlayer(client); - - /* Make sure the team is valid */ - int team = player->pInfo->GetTeamIndex(); - if (team != CS_TEAM_T && team != CS_TEAM_CT) - { - return Pl_Stop; - } - - /* Make sure they're dead */ - if (DM_IsPlayerAlive(client)) - { - return Pl_Stop; - } - - DM_RespawnPlayer(client); - - return Pl_Stop; - } - - void OnTimerEnd(ITimer *pTimer, void *pData) override - { - DMData *data = static_cast(pData); - int client = data->index; - - dm_player_t *player = DM_GetPlayer(client); - if (player->respawn_timer == pTimer) - { - player->respawn_timer = NULL; - } - - delete (DMData *)pData; - } -} s_PlayerSpawner; - -void DM_ClearRagdollTimers() -{ - auto iter = g_RagdollTimers.begin(); - while (iter != g_RagdollTimers.end()) - { - timersys->KillTimer((*iter)); - iter = g_RagdollTimers.erase(iter); - } -} - -void DM_SchedRespawn(int client) -{ - dm_player_t *player = DM_GetPlayer(client); - - if (player->respawn_timer) - { - timersys->KillTimer(player->respawn_timer); - } - - DMData *data = new DMData(client); - - player->respawn_timer = timersys->CreateTimer(&s_PlayerSpawner, DM_GetRespawnWait(), data, 0); -} - -void OnClientCommand_Post(edict_t *edict, const CCommand &args) -{ - if (!g_IsRunning) - { - return; - } - - const char *cmd = args.Arg(0); - - if (strcmp(cmd, "joinclass") == 0) - { - int client = gamehelpers->IndexOfEdict(edict); - dm_player_t *player = DM_GetPlayer(client); - if (!player || !player->pEntity) - { - return; - } - - if (DM_IsPlayerAlive(client)) - { - return; - } - - if (!player->will_respawn_on_class) - { - return; - } - - player->will_respawn_on_class = false; - - /* Respawn! */ - DM_SchedRespawn(client); - } -} - -#define IMPLEMENT_EVENT(name) \ - cls_event_##name g_cls_event_##name; \ - void cls_event_##name::FireGameEvent(IGameEvent *event) - -IMPLEMENT_EVENT(player_death) -{ - if (!g_IsRunning) - { - return; - } - - int userid = event->GetInt("userid"); - - int client = playerhelpers->GetClientOfUserId(userid); - if (!client) - { - return; - } - - dm_player_t *player = DM_GetPlayer(client); - if (!player || !player->pEntity) - { - return; - } - - player->is_spawned = false; - - /* Remove ragdoll */ - unsigned int ragdollTime = DM_GetBodyStayTime(); - if (ragdollTime <= 20 && !g_InRoundRestart) - { - int serial; - CBaseEntity *ragdoll = DM_GetAndClearRagdoll(player->pEntity, serial); - if (ragdollTime == 0) - { - DM_RemoveEntity(ragdoll); - } else { - edict_t *pEdict = gameents->BaseEntityToEdict(ragdoll); - if (pEdict) - { - int index = gamehelpers->IndexOfEdict(pEdict); - DMData *data = new DMData(index, serial); - - ITimer *timer = timersys->CreateTimer(&s_RagdollRemover, ragdollTime, data, 0); - g_RagdollTimers.push_back(timer); - } - } - } - - if (!DM_OnClientDeath(client)) - { - return; - } - - DM_SchedRespawn(client); -} - -IMPLEMENT_EVENT(player_team) -{ - if (!g_IsRunning) - { - return; - } - - int userid = event->GetInt("userid"); - int client = playerhelpers->GetClientOfUserId(userid); - if (!client) - { - return; - } - - dm_player_t *player = DM_GetPlayer(client); - if (!player || !player->pEntity) - { - return; - } - - if (DM_IsPlayerAlive(client) || event->GetBool("disconnect")) - { - return; - } - - int old_team = event->GetInt("oldteam"); - if (old_team == CS_TEAM_T || old_team == CS_TEAM_CT) - { - return; - } - - int new_team = event->GetInt("team"); - if (new_team != CS_TEAM_T && new_team != CS_TEAM_CT) - { - return; - } - - if (player->pBot) - { - DM_SchedRespawn(client); - } else { - player->will_respawn_on_class = true; - } -} - -IMPLEMENT_EVENT(player_spawn) -{ - if (!g_IsRunning) - { - return; - } - - int userid = event->GetInt("userid"); - int client = playerhelpers->GetClientOfUserId(userid); - if (!client) - { - return; - } - - dm_player_t *player = DM_GetPlayer(client); - if (!player || !player->pEntity || (player->is_spawned && !g_InRoundRestart)) - { - return; - } - - /* This can be fired before a player gets a team! */ - int team_idx = player->pInfo->GetTeamIndex(); - if (team_idx != CS_TEAM_T - && team_idx != CS_TEAM_CT) - { - return; - } - - bool old_value = player->is_spawned; - player->is_spawned = true; - - /* If we were waiting to respawn, cancel the timer */ - if (player->respawn_timer && !player->pBot) - { - timersys->KillTimer(player->respawn_timer); - player->respawn_timer = NULL; - } - - DM_OnClientSpawned(client, old_value); -} - -IMPLEMENT_EVENT(server_shutdown) -{ - g_IsInGlobalShutdown = true; -} - -IMPLEMENT_EVENT(round_start) -{ - g_InRoundRestart = false; -} - -IMPLEMENT_EVENT(round_end) -{ - g_InRoundRestart = true; - - DM_ClearRagdollTimers(); - - for (int i=1; i<=gpGlobals->maxClients; i++) - { - dm_player_t *player = DM_GetPlayer(i); - player->is_spawned = false; - } -} diff --git a/cssdm_events.h b/cssdm_events.h deleted file mode 100644 index 22321a8..0000000 --- a/cssdm_events.h +++ /dev/null @@ -1,79 +0,0 @@ -/** - * vim: set ts=4 : - * =============================================================== - * CS:S DM, Copyright (C) 2004-2007 AlliedModders LLC. - * By David "BAILOPAN" Anderson - * 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 as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Version: $Id$ - */ - -#ifndef _INCLUDE_CSSDM_EVENTS_H_ -#define _INCLUDE_CSSDM_EVENTS_H_ - -#include -#include -#include - -#if SOURCE_ENGINE == SE_CSGO -#define DECLARE_EVENT(name) \ - class cls_event_##name : public IGameEventListener2 \ - { \ - public: \ - void FireGameEvent(IGameEvent *event) override; \ - int GetEventDebugID( void ) override { return EVENT_DEBUG_ID_INIT; } \ - }; \ - extern cls_event_##name g_cls_event_##name; -#else -#define DECLARE_EVENT(name) \ - class cls_event_##name : public IGameEventListener2 \ - { \ - public: \ - void FireGameEvent(IGameEvent *event) override; \ - }; \ - extern cls_event_##name g_cls_event_##name; -#endif - -DECLARE_EVENT(player_death); -DECLARE_EVENT(player_spawn); -DECLARE_EVENT(player_team); -DECLARE_EVENT(server_shutdown); -DECLARE_EVENT(round_start); -DECLARE_EVENT(round_end); - -class CCommand; - -void DM_ClearRagdollTimers(); -void OnClientCommand_Post(edict_t *edict, const CCommand &args); - -class DMData -{ -public: - DMData(int iIndex, int iSerial = 0) - { - this->index = iIndex; - this->serial = iSerial; - } - -public: - int index; - int serial; -}; - -#endif //_INCLUDE_CSSDM_EVENTS_H_ diff --git a/cssdm_ffa.cpp b/cssdm_ffa.cpp deleted file mode 100644 index 56154de..0000000 --- a/cssdm_ffa.cpp +++ /dev/null @@ -1,249 +0,0 @@ -/** - * vim: set ts=4 : - * =============================================================== - * CS:S DM, Copyright (C) 2004-2007 AlliedModders LLC. - * By David "BAILOPAN" Anderson - * 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 as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Version: $Id$ - */ - -#include -#include "cssdm_headers.h" -#include "cssdm_utils.h" -#include "sm_platform.h" -#include "cssdm_includesdk.h" - -// Don't patch anything on CSGO -#if SOURCE_ENGINE != SE_CSGO -SH_DECL_MANUALHOOK2(CGameRules_IPointsForKill, 62+EXTRA_VTBL_OFFSET, 0, 0, int, CBasePlayer *, CBasePlayer *); - -#if defined PLATFORM_64BITS -#define PLATFORM_ARCH_SUFFIX "64" -#else -#define PLATFORM_ARCH_SUFFIX "" -#endif - -#if defined PLATFORM_WINDOWS -#define PLATFORM_NAME "Windows" PLATFORM_ARCH_SUFFIX -#elif defined PLATFORM_LINUX -#define PLATFORM_NAME "Linux" PLATFORM_ARCH_SUFFIX -#elif defined __APPLE__ -#define PLATFORM_NAME "Mac" PLATFORM_ARCH_SUFFIX -#endif - -bool g_FFA_Patched = false; -bool g_FFA_PointsHooked = false; -bool g_FFA_Prepared = false; - -void *g_gamerules_addr = NULL; - -/* Lagcomp */ -static int g_lagcomp_offset = 0; -static void *g_lagcomp_addr = NULL; -static dmpatch_t g_lagcomp_patch; -static dmpatch_t g_lagcomp_restore; - -/* Takedamage */ -static int g_takedmg_offset[5] = {0}; -static void *g_takedmg_addr = NULL; -static dmpatch_t g_takedmg_patch[2]; -static dmpatch_t g_takedmg_restore[2]; - -/* Calc domination and revenge */ -static int g_domrev_offset = 0; -static void *g_domrev_addr = NULL; -static dmpatch_t g_domrev_patch; -static dmpatch_t g_domrev_restore; - -int OnIPointsForKill(CBasePlayer *pl1, CBasePlayer *pl2) -{ - /* If we're hooked, FFA is always on. */ - RETURN_META_VALUE(MRES_SUPERCEDE, 1); -} - -bool DM_FFA_LoadPatch(const char *name, dmpatch_t *patch, char *error, size_t maxlength) -{ - char fullname[255]; - snprintf(fullname, sizeof(fullname), "%s_%s", name, PLATFORM_NAME); - - const char *str = g_pDmConf->GetKeyValue(fullname); - if (!str) - { - snprintf(error, maxlength, "Could not find signature value for \"%s\"", fullname); - return false; - } - - patch->bytes = DM_StringToBytes(str, patch->patch, sizeof(patch->patch)); - if (!patch->bytes) - { - snprintf(error, maxlength, "Invalid signature detected for \"%s\"", fullname); - return false; - } - - return true; -} - -bool DM_Prepare_FFA(char *error, size_t maxlength) -{ - void *gamerules = NULL; - if (!g_pDmConf->GetMemSig("OnTakeDamage", &g_takedmg_addr) || !g_takedmg_addr) - { - snprintf(error, maxlength, "Could not find \"OnTakeDamage\" signature!"); - return false; - } - if (!g_pDmConf->GetMemSig("WantsLagComp", &g_lagcomp_addr) || !g_lagcomp_addr) - { - snprintf(error, maxlength, "Could not find \"WantsLagComp\" signature!"); - return false; - } - if (!g_pDmConf->GetMemSig("CalcDominationAndRevenge", &g_domrev_addr) || !g_domrev_addr) - { - snprintf(error, maxlength, "Could not find \"CalcDominationAndRevenge\" signature!"); - return false; - } - - if (!g_pDmConf->GetOffset("LagCompPatch", &g_lagcomp_offset) - || !g_lagcomp_offset) - { - snprintf(error, maxlength, "Could not find LagCompPatch offset"); - return false; - } - if (!DM_FFA_LoadPatch("LagCompPatch", &g_lagcomp_patch, error, maxlength)) - { - return false; - } - - if (!g_pDmConf->GetOffset("CalcDomRevPatch", &g_domrev_offset) - || !g_domrev_offset) - { - snprintf(error, maxlength, "Could not find CalcDomRevPatch offset"); - return false; - } - if (!DM_FFA_LoadPatch("CalcDomRevPatch", &g_domrev_patch, error, maxlength)) - { - return false; - } - - if (!g_pDmConf->GetOffset("TakeDmgPatch1", &g_takedmg_offset[0]) - || !g_takedmg_offset[0]) - { - snprintf(error, maxlength, "Could not find TakeDmgPatch1 offset"); - return false; - } - if (!DM_FFA_LoadPatch("TakeDmgPatch1", &g_takedmg_patch[0], error, maxlength)) - { - return false; - } - - /* Load the GameRules pointer */ - if (!sdktools) - { - snprintf(error, maxlength, "SDKTools not loaded"); - return false; - } - /* Get the GameRules address later when map starts */ - - /* Get the "IPointsForKill" offset */ - int offset; - if (!g_pDmConf->GetOffset("IPointsForKill", &offset) - || !offset) - { - snprintf(error, maxlength, "Could not find IPointsForKills offset"); - return false; - } - SH_MANUALHOOK_RECONFIGURE(CGameRules_IPointsForKill, offset, 0, 0); - - g_FFA_Prepared = true; - - return true; -} - -bool LoadGameRulesAddress() -{ - if (!sdktools) - { - g_pSM->LogError(myself, "SDKTools not loaded. FFA points hook will not work."); - return false; - } - g_gamerules_addr = sdktools->GetGameRules(); - if (!g_gamerules_addr) - { - g_pSM->LogError(myself, "Could not find GameRules address. FFA points hook will not work."); - return false; - } - return true; -} - -bool DM_Patch_FFA() -{ - if (g_FFA_Patched || !g_FFA_Prepared) - { - return false; - } - - DM_ApplyPatch(g_lagcomp_addr, g_lagcomp_offset, &g_lagcomp_patch, &g_lagcomp_restore); - DM_ApplyPatch(g_takedmg_addr, g_takedmg_offset[0], &g_takedmg_patch[0], &g_takedmg_restore[0]); - DM_ApplyPatch(g_domrev_addr, g_domrev_offset, &g_domrev_patch, &g_domrev_restore); - - // needs a new gamerules address on every map load - if (!g_FFA_PointsHooked && LoadGameRulesAddress()) - { - SH_ADD_MANUALHOOK_STATICFUNC(CGameRules_IPointsForKill, g_gamerules_addr, OnIPointsForKill, false); - g_FFA_PointsHooked = true; - } - - g_FFA_Patched = true; - - return true; -} - -bool DM_Unpatch_FFA() -{ - if (!g_FFA_Patched) - { - return false; - } - - // g_gamerules_addr won't be null if we're already hooked - if (!g_IsInGlobalShutdown && g_FFA_PointsHooked) - { - SH_REMOVE_MANUALHOOK_STATICFUNC(CGameRules_IPointsForKill, g_gamerules_addr, OnIPointsForKill, false); - g_FFA_PointsHooked = false; - } - - DM_ApplyPatch(g_lagcomp_addr, g_lagcomp_offset, &g_lagcomp_restore, NULL); - DM_ApplyPatch(g_takedmg_addr, g_takedmg_offset[0], &g_takedmg_restore[0], NULL); - DM_ApplyPatch(g_domrev_addr, g_domrev_offset, &g_domrev_restore, NULL); - - g_FFA_Patched = false; - - return true; -} - -bool DM_FFA_IsPatched() -{ - return g_FFA_Patched; -} - -bool DM_FFA_IsPrepared() -{ - return g_FFA_Prepared; -} -#endif diff --git a/cssdm_ffa.h b/cssdm_ffa.h deleted file mode 100644 index 1054a6f..0000000 --- a/cssdm_ffa.h +++ /dev/null @@ -1,40 +0,0 @@ -/** - * vim: set ts=4 : - * =============================================================== - * CS:S DM, Copyright (C) 2004-2007 AlliedModders LLC. - * By David "BAILOPAN" Anderson - * 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 as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Version: $Id$ - */ - -#ifndef _INCLUDE_CSSDM_FFA_H_ -#define _INCLUDE_CSSDM_FFA_H_ - -#if SOURCE_ENGINE != SE_CSGO -bool DM_FFA_IsPatched(); -bool DM_FFA_IsPrepared(); - -/* Internal */ -bool DM_Prepare_FFA(char *error, size_t maxlength); -bool DM_Unpatch_FFA(); -bool DM_Patch_FFA(); -#endif - -#endif //_INCLUDE_CSSDM_FFA_H_ diff --git a/cssdm_headers.h b/cssdm_headers.h deleted file mode 100644 index 419af8d..0000000 --- a/cssdm_headers.h +++ /dev/null @@ -1,51 +0,0 @@ -/** - * vim: set ts=4 : - * =============================================================== - * CS:S DM, Copyright (C) 2004-2007 AlliedModders LLC. - * By David "BAILOPAN" Anderson - * 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 as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Version: $Id$ - */ - -#ifndef _INCLUDE_CSSDM_HEADERS_H_ -#define _INCLUDE_CSSDM_HEADERS_H_ - -#include -#include -#include -#include "smsdk_ext.h" -#include -#include - -extern IBinTools *bintools; -extern ISDKTools* sdktools; -extern IPlayerInfoManager *playerinfomngr; -extern IBaseFileSystem *basefilesystem; -extern IGameConfig *g_pDmConf; -extern CGlobalVars *gpGlobals; -extern IServerGameEnts *gameents; -extern IServerGameClients *gameclients; -extern IBotManager *botmanager; -extern bool g_IsRunning; -extern bool g_IsInGlobalShutdown; -extern ISourcePawnEngine *spengine; -extern ICvar *icvar; - -#endif //_INCLUDE_CSSDM_HEADERS_H_ diff --git a/cssdm_includesdk.h b/cssdm_includesdk.h deleted file mode 100644 index 3cab658..0000000 --- a/cssdm_includesdk.h +++ /dev/null @@ -1,42 +0,0 @@ -/** - * vim: set ts=4 : - * =============================================================== - * CS:S DM, Copyright (C) 2004-2007 AlliedModders LLC. - * By David "BAILOPAN" Anderson - * 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 as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Version: $Id$ - */ - -#ifndef _INCLUDE_CSSDM_INCLUDESDK_H_ -#define _INCLUDE_CSSDM_INCLUDESDK_H_ - -#define GAME_DLL 1 -#if defined _DEBUG -#define RESET_DEBUG -#undef _DEBUG -#endif -//#include "cbase.h" -//#include "baseentity.h" -class CBasePlayer; -#if defined RESET_DEBUG -#define _DEBUG -#endif - -#endif //_INCLUDE_CSSDM_INCLUDESDK_H_ diff --git a/cssdm_main.cpp b/cssdm_main.cpp deleted file mode 100644 index 75d4c0c..0000000 --- a/cssdm_main.cpp +++ /dev/null @@ -1,263 +0,0 @@ -/** - * vim: set ts=4 : - * =============================================================== - * CS:S DM, Copyright (C) 2004-2007 AlliedModders LLC. - * By David "BAILOPAN" Anderson - * 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 as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Version: $Id$ - */ - -#include "cssdm_main.h" -#include "cssdm_headers.h" -#include "cssdm_utils.h" -#include "cssdm_events.h" -#include "cssdm_players.h" -#include "cssdm_ctrl.h" -#include "cssdm_config.h" -#include "cssdm_ffa.h" -#include "cssdm_callbacks.h" -#include "cssdm_weapons.h" -#include "cssdm_version.h" - -SH_DECL_HOOK0_void(IServerGameDLL, DLLShutdown, SH_NOATTRIB, false); -SH_DECL_HOOK2_void(IServerGameClients, ClientCommand, SH_NOATTRIB, false, edict_t *, const CCommand &); - -Deathmatch g_DM; -IGameEventManager2 *gameevents = NULL; -IBaseFileSystem *basefilesystem = NULL; -IBinTools *bintools = NULL; -ISDKTools *sdktools = NULL; -IGameConfig *g_pDmConf = NULL; -CGlobalVars *gpGlobals = NULL; -IPlayerInfoManager *playerinfomngr = NULL; -IServerGameEnts *gameents = NULL; -IServerGameClients *gameclients = NULL; -ISourcePawnEngine *spengine = NULL; -IBotManager *botmanager = NULL; -ICvar *icvar = NULL; -char g_GlobError[255] = {0}; -bool g_IsLoadedOkay = false; -bool g_Startup = false; -bool g_IsInGlobalShutdown = false; - -SMEXT_LINK(&g_DM); - -#define VERIFY_SIGNATURE(name) \ - if (!g_pDmConf->GetMemSig(name, &addr) || !addr) { \ - snprintf(error, maxlength, "Could not find signature \"%s\"", name); \ - return false; \ - } - -#define VERIFY_OFFSET(name) \ - if (!g_pDmConf->GetOffset(name, &offset) || !offset) { \ - snprintf(error, maxlength, "Could not find offset \"%s\"", name); \ - return false; \ - } - -#define HOOK_EVENT2(name) \ - if (!gameevents->AddListener(&g_cls_event_##name, #name, true)) { \ - snprintf(error, maxlength, "Could not hook event \"%s\"", #name); \ - return false; \ - } - -#define UNHOOK_EVENT2(name) gameevents->RemoveListener(&g_cls_event_##name); - -bool Deathmatch::SDK_OnLoad(char *error, size_t maxlength, bool late) -{ - sharesys->AddDependency(myself, "bintools.ext", true, true); - sharesys->AddDependency(myself, "sdktools.ext", true, true); - sharesys->RegisterLibrary(myself, "cssdm"); - sharesys->AddNatives(myself, g_BaseNatives); - if (!gameconfs->LoadGameConfigFile("cssdm.games", &g_pDmConf, error, maxlength)) - { - return false; - } - - void *addr; - int offset; - VERIFY_SIGNATURE("RoundRespawn"); - VERIFY_OFFSET("RemoveAllItems"); - - if (!DM_ParseWeapons(error, maxlength)) - { - return false; - } - - gpGlobals = g_SMAPI->GetCGlobals(); - - SM_InitConCommandBase(); - - spengine = g_pSM->GetScriptingEngine(); - - return true; -} - -bool Deathmatch::SDK_OnMetamodLoad(ISmmAPI *ismm, char *error, size_t maxlen, bool late) -{ - GET_V_IFACE_CURRENT(GetEngineFactory, gameevents, IGameEventManager2, INTERFACEVERSION_GAMEEVENTSMANAGER2); - GET_V_IFACE_CURRENT(GetFileSystemFactory, basefilesystem, IBaseFileSystem, BASEFILESYSTEM_INTERFACE_VERSION); - GET_V_IFACE_ANY(GetServerFactory, playerinfomngr, IPlayerInfoManager, INTERFACEVERSION_PLAYERINFOMANAGER); - GET_V_IFACE_ANY(GetServerFactory, gameents,IServerGameEnts, INTERFACEVERSION_SERVERGAMEENTS); - GET_V_IFACE_ANY(GetServerFactory, botmanager, IBotManager, INTERFACEVERSION_PLAYERBOTMANAGER); - GET_V_IFACE_ANY(GetServerFactory, gameclients, IServerGameClients, INTERFACEVERSION_SERVERGAMECLIENTS); - GET_V_IFACE_CURRENT(GetEngineFactory, icvar, ICvar, CVAR_INTERFACE_VERSION); - - return true; -} - -void OnDLLShutdown() -{ - g_IsInGlobalShutdown = true; - RETURN_META(MRES_IGNORED); -} - -bool Startup(char *error, size_t maxlength) -{ - playerhelpers->AddClientListener(&g_ClientListener); - - HOOK_EVENT2(player_death); - HOOK_EVENT2(player_spawn); - HOOK_EVENT2(player_team); - HOOK_EVENT2(round_start); - HOOK_EVENT2(round_end); - HOOK_EVENT2(server_shutdown); - - g_Startup = true; - - SH_ADD_HOOK_STATICFUNC(IServerGameDLL, DLLShutdown, gamedll, OnDLLShutdown, false); - SH_ADD_HOOK_STATICFUNC(IServerGameClients, ClientCommand, gameclients, OnClientCommand_Post, true); - - DM_InitCallbacks(); - -#if SOURCE_ENGINE != SE_CSGO - char ffa_error[255]; - if (!DM_Prepare_FFA(ffa_error, sizeof(ffa_error))) - { - g_pSM->LogError(myself, "FFA will not work: %s", ffa_error); - } -#endif - - return InitializeUtils(error, maxlength); -} - -void Shutdown() -{ - /* Remove hooks that could have happened whether we got started up or not */ - playerhelpers->RemoveClientListener(&g_ClientListener); - - UNHOOK_EVENT2(player_death); - UNHOOK_EVENT2(player_spawn); - UNHOOK_EVENT2(player_team); - UNHOOK_EVENT2(round_start); - UNHOOK_EVENT2(round_end); - UNHOOK_EVENT2(server_shutdown); - - /* If we were never started up, the rest of this is invalid */ - if (!g_Startup) - { - return; - } - - /* Make sure stuff like FFA is cleaned up */ - DM_Disable(); - - /* Destroy various internal things */ - DM_ShutdownCallbacks(); - DM_FreeWeapons(); - ShutdownUtils(); - - /* Unhook everything from SourceHook */ - SH_REMOVE_HOOK_STATICFUNC(IServerGameClients, ClientCommand, gameclients, OnClientCommand_Post, true); - SH_REMOVE_HOOK_STATICFUNC(IServerGameDLL, DLLShutdown, gamedll, OnDLLShutdown, false); -} - -void Deathmatch::SDK_OnAllLoaded() -{ - SM_GET_LATE_IFACE(BINTOOLS, bintools); - SM_GET_LATE_IFACE(SDKTOOLS, sdktools); - - g_IsLoadedOkay = Startup(g_GlobError, sizeof(g_GlobError)); - - if (!QueryRunning(NULL, 0)) - { - return; - } -} - -void Deathmatch::SDK_OnUnload() -{ - DM_FreeWeapons(); - Shutdown(); - gameconfs->CloseGameConfigFile(g_pDmConf); -} - -bool Deathmatch::QueryRunning(char *error, size_t maxlength) -{ - SM_CHECK_IFACE(BINTOOLS, bintools); - SM_CHECK_IFACE(SDKTOOLS, sdktools); - - if (!g_IsLoadedOkay && g_GlobError[0] != '\0') - { - snprintf(error, maxlength, "%s", g_GlobError); - return false; - } - - return true; -} - -void Deathmatch::OnCoreMapStart(edict_t *pEdictList, int edictCount, int clientMax) -{ - OnLevelInitialized(); -} - -void Deathmatch::OnCoreMapEnd() -{ - OnLevelEnd(); -} - -bool Deathmatch::QueryInterfaceDrop(SMInterface *pInterface) -{ - if (pInterface == bintools || pInterface == sdktools) - { - return false; - } - - return true; -} - -void Deathmatch::NotifyInterfaceDrop(SMInterface *pInterface) -{ - /* We have to take care of bintools early then... */ - if (pInterface == bintools) - { - ShutdownUtils(); - bintools = NULL; - } - if (pInterface == sdktools) - { - sdktools = NULL; - } -} - -const char *Deathmatch::GetExtensionVerString() -{ - return CSSDM_FULL_VERSION; -} - diff --git a/cssdm_main.h b/cssdm_main.h deleted file mode 100644 index a9750a8..0000000 --- a/cssdm_main.h +++ /dev/null @@ -1,63 +0,0 @@ -/** - * vim: set ts=4 : - * =============================================================== - * CS:S DM, Copyright (C) 2004-2007 AlliedModders LLC. - * By David "BAILOPAN" Anderson - * 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 as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Version: $Id$ - */ - - -#ifndef _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_ -#define _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_ - -/** - * @file extension.h - * @brief Sample extension code header. - */ - -#include - -/** - * @brief Sample implementation of the SDK Extension. - * Note: Uncomment one of the pre-defined virtual functions in order to use it. - */ -class Deathmatch : public SDKExtension -{ -public: - bool SDK_OnLoad(char *error, size_t maxlength, bool late) override; - void SDK_OnUnload() override; - void SDK_OnAllLoaded() override; - //virtual void SDK_OnPauseChange(bool paused); - bool QueryRunning(char *error, size_t maxlength) override; - void OnCoreMapStart(edict_t *pEdictList, int edictCount, int clientMax) override; - void OnCoreMapEnd() override; - bool QueryInterfaceDrop(SMInterface *pInterface) override; - void NotifyInterfaceDrop(SMInterface *pInterface) override; - const char *GetExtensionVerString() override; -public: - bool SDK_OnMetamodLoad(ISmmAPI *ismm, char *error, size_t maxlength, bool late) override; - //virtual bool SDK_OnMetamodUnload(char *error, size_t maxlength); - //virtual bool SDK_OnMetamodPauseChange(bool paused, char *error, size_t maxlength); -}; - -extern Deathmatch g_DM; - -#endif // _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_ diff --git a/cssdm_players.cpp b/cssdm_players.cpp deleted file mode 100644 index 1ad934e..0000000 --- a/cssdm_players.cpp +++ /dev/null @@ -1,101 +0,0 @@ -/** - * vim: set ts=4 : - * =============================================================== - * CS:S DM, Copyright (C) 2004-2007 AlliedModders LLC. - * By David "BAILOPAN" Anderson - * 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 as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Version: $Id$ - */ - -#include "cssdm_players.h" -#include "cssdm_headers.h" -#include "cssdm_utils.h" -#include "cssdm_config.h" -#include "cssdm_includesdk.h" - -ClientListener g_ClientListener; -dm_player_t g_players[SM_MAXPLAYERS]; - -void DM_ResetPlayer(int client); -void DM_ActivatePlayer(int client); - -void ClientListener::OnClientConnected(int client) -{ - memset(&g_players[client], 0, sizeof(dm_player_t)); -} - -void ClientListener::OnClientDisconnecting(int client) -{ - dm_player_t *player = DM_GetPlayer(client); - - DM_ResetPlayer(client); -} - -void ClientListener::OnClientPutInServer(int client) -{ - DM_ActivatePlayer(client); -} - -void DM_ResetPlayer(int client) -{ - dm_player_t *player = DM_GetPlayer(client); - if (!player) - { - return; - } - - if (player->respawn_timer) - { - timersys->KillTimer(player->respawn_timer); - } - - memset(player, 0, sizeof(dm_player_t)); -} - -void DM_ActivatePlayer(int client) -{ - dm_player_t *player = DM_GetPlayer(client); - if (!player) - { - return; - } - - CBaseEntity *pEntity = DM_GetBaseEntity(client); - if (!pEntity) - { - return; - } - - player->pEdict = gamehelpers->EdictOfIndex(client); - player->pEntity = pEntity; - player->pInfo = playerinfomngr->GetPlayerInfo(player->pEdict); - player->pBot = botmanager->GetBotController(player->pEdict); - player->userid = engine->GetPlayerUserId(player->pEdict); -} - -dm_player_t *DM_GetPlayer(int client) -{ - if (client < 1 || client > gpGlobals->maxClients) - { - return NULL; - } - - return &g_players[client]; -} diff --git a/cssdm_players.h b/cssdm_players.h deleted file mode 100644 index 17baf1c..0000000 --- a/cssdm_players.h +++ /dev/null @@ -1,57 +0,0 @@ -/** - * vim: set ts=4 : - * =============================================================== - * CS:S DM, Copyright (C) 2004-2007 AlliedModders LLC. - * By David "BAILOPAN" Anderson - * 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 as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Version: $Id$ - */ - -#ifndef _INCLUDE_CSSDM_PLAYERS_H_ -#define _INCLUDE_CSSDM_PLAYERS_H_ - -#include "smsdk_ext.h" -#include - -struct dm_player_t -{ - edict_t *pEdict; - CBaseEntity *pEntity; - IPlayerInfo *pInfo; - IBotController *pBot; - ITimer *respawn_timer; - int userid; - bool is_spawned; - bool will_respawn_on_class; -}; - -class ClientListener : public IClientListener -{ -public: - void OnClientConnected(int client) override; - void OnClientPutInServer(int client) override; - void OnClientDisconnecting(int client) override; -}; - -dm_player_t *DM_GetPlayer(int client); - -extern ClientListener g_ClientListener; - -#endif //_INCLUDE_CSSDM_PLAYERS_H_ diff --git a/cssdm_utils.cpp b/cssdm_utils.cpp deleted file mode 100644 index 9189906..0000000 --- a/cssdm_utils.cpp +++ /dev/null @@ -1,297 +0,0 @@ -/** - * vim: set ts=4 : - * =============================================================== - * CS:S DM, Copyright (C) 2004-2007 AlliedModders LLC. - * By David "BAILOPAN" Anderson - * 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 as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Version: $Id$ - */ - -#include - -#include "cssdm_headers.h" -#include "cssdm_players.h" -#include "cssdm_utils.h" -#include "cssdm_includesdk.h" -#include - -std::list g_CallWrappers; -ICallWrapper *g_pRoundRespawn = NULL; -ICallWrapper *g_pRemoveAllItems = NULL; -ICallWrapper *g_pGiveAmmo = NULL; -int g_RagdollOffset = 0; -int g_LifeStateOffset = 0; - -void DM_ProtectMemory(void *addr, int length, int prot); - -CBaseEntity *DM_GetBaseEntity(int index) -{ - edict_t *pEdict = gamehelpers->EdictOfIndex(index); - if (!pEdict || pEdict->IsFree()) - { - return NULL; - } - IServerUnknown *pUnknown = pEdict->GetUnknown(); - if (!pUnknown) - { - return NULL; - } - return pUnknown->GetBaseEntity(); -} - -CBaseEntity *DM_GetAndClearRagdoll(CBaseEntity *pEntity, int &serial) -{ - if (!g_RagdollOffset) - { - return NULL; - } - - unsigned char *ptr = reinterpret_cast(pEntity) + g_RagdollOffset; - CBaseHandle &ph = *reinterpret_cast(ptr); - - if (!ph.IsValid()) - { - return NULL; - } - - int index = ph.GetEntryIndex(); - serial = ph.GetSerialNumber(); - - if (!index) - { - return NULL; - } - - CBaseEntity *pRagdoll = DM_GetBaseEntity(index); - - ph.Set(NULL); - - return pRagdoll; -} - -void DM_RespawnPlayer(int client) -{ - dm_player_t *player = DM_GetPlayer(client); - if (!player || !player->pEntity) - { - return; - } - - if (player->respawn_timer) - { - timersys->KillTimer(player->respawn_timer); - player->respawn_timer = NULL; - } - - CBaseEntity *pEntity = player->pEntity; - g_pRoundRespawn->Execute(&pEntity, NULL); -} - -class variant_t -{ -public: - union - { - bool bVal; - string_t iszVal; - int iVal; - float flVal; - float vecVal[3]; - color32 rgbaVal; - }; - CBaseHandle eVal; // this can't be in the union because it has a constructor. - fieldtype_t fieldType; -}; - -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. -}; - -void DM_RemoveEntity(CBaseEntity *pEntity) -{ - datamap_t *pMap = gamehelpers->GetDataMap(pEntity); - - if(!pMap) - return; - - typedescription_t *pDesc = gamehelpers->FindInDataMap(pMap, "InputKill"); - - if(!pDesc) - return; - - inputdata_t data; - (pEntity->*pDesc->inputFunc)(data); -} - -bool DM_IsPlayerAlive(int client) -{ - dm_player_t *player = DM_GetPlayer(client); - if (!player || !player->pEntity || !g_LifeStateOffset) - { - return false; - } - - if (!g_LifeStateOffset) - { - return player->pInfo->IsDead() ? false : true; - } - - unsigned char *ptr = reinterpret_cast(player->pEntity) + g_LifeStateOffset; - return (*reinterpret_cast(ptr) == LIFE_ALIVE); -} - -bool DM_CheckSerial(edict_t *pEdict, int serial) -{ - int new_serial = (serial & ((1 << NUM_NETWORKED_EHANDLE_SERIAL_NUMBER_BITS) - 1)); - return (pEdict->m_NetworkSerialNumber == new_serial); -} - -void DM_RemoveAllItems(CBaseEntity *pEntity, bool removeSuit) -{ - unsigned char vstk[sizeof(CBaseEntity *) + sizeof(bool)]; - unsigned char *vptr = vstk; - - *reinterpret_cast(vptr) = pEntity; - vptr += sizeof(CBaseEntity *); - *reinterpret_cast(vptr) = removeSuit; - //vptr += sizeof(bool); - - g_pRemoveAllItems->Execute(vstk, NULL); -} - -size_t DM_StringToBytes(const char *str, unsigned char buffer[], size_t maxlength) -{ - size_t real_bytes = 0; - size_t length = strlen(str); - - for (size_t i=0; i= maxlength) - { - break; - } - buffer[real_bytes++] = static_cast(str[i]); - if (str[i] == '\\' - && str[i+1] == 'x') - { - if (i + 3 >= length) - { - continue; - } - /* Get the hex part */ - char s_byte[3]; - int r_byte; - s_byte[0] = str[i+2]; - s_byte[1] = str[i+3]; - s_byte[2] = '\n'; - /* Read it as an integer */ - sscanf(s_byte, "%x", &r_byte); - /* Save the value */ - buffer[real_bytes-1] = static_cast(r_byte); - /* Adjust index */ - i += 3; - } - } - - return real_bytes; -} - -void DM_ApplyPatch(void *address, int offset, const dmpatch_t *patch, dmpatch_t *restore) -{ - unsigned char *addr = (unsigned char *)address + offset; - - DM_SetMemPatchable(addr, 20); - - if (restore) - { - for (size_t i=0; ibytes; i++) - { - restore->patch[i] = addr[i]; - } - restore->bytes = patch->bytes; - } - - for (size_t i=0; ibytes; i++) - { - addr[i] = patch->patch[i]; - } -} - -void DM_SetMemPatchable(void *address, size_t size) -{ - SourceHook::SetMemAccess(address, size, SH_MEM_READ|SH_MEM_WRITE|SH_MEM_EXEC); -} - -#define GET_PROPERTY(cls, name, var) \ - if ( (prop = gamehelpers->FindInSendTable(cls, name)) == NULL ) { \ - snprintf(error, maxlength, "Could not find property: %s", name); \ - return false; \ - } \ - var = prop->GetOffset(); - -bool InitializeUtils(char *error, size_t maxlength) -{ - void *addr; - int offset; - SourceMod::PassInfo pass[4]; - - /** ROUNDRESPAWN */ - g_pDmConf->GetMemSig("RoundRespawn", &addr); - g_pRoundRespawn = bintools->CreateCall(addr, CallConv_ThisCall, NULL, NULL, 0); - g_CallWrappers.push_back(g_pRoundRespawn); - - /** REMOVEALLITEMS */ - g_pDmConf->GetOffset("RemoveAllItems", &offset); - pass[0].flags = PASSFLAG_BYVAL; - pass[0].size = sizeof(bool); - pass[0].type = PassType_Basic; - g_pRemoveAllItems = bintools->CreateVCall(offset, 0, 0, NULL, pass, 1); - g_CallWrappers.push_back(g_pRemoveAllItems); - - /** PROPERTIES */ - sm_sendprop_info_t prop; - if(!gamehelpers->FindSendPropInfo("CCSPlayer", "m_hRagdoll", &prop)) - { - snprintf(error, maxlength, "Failed to get prop info for m_hRagdoll"); - return false; - } - g_RagdollOffset = prop.actual_offset; - if(!gamehelpers->FindSendPropInfo("CCSPlayer", "m_lifeState", &prop)) - { - snprintf(error, maxlength, "Failed to get prop info for m_lifeState"); - return false; - } - g_LifeStateOffset = prop.actual_offset; - - return true; -} - -void ShutdownUtils() -{ - for (auto i : g_CallWrappers) - { - i->Destroy(); - } - g_CallWrappers.clear(); -} diff --git a/cssdm_utils.h b/cssdm_utils.h deleted file mode 100644 index ee69dae..0000000 --- a/cssdm_utils.h +++ /dev/null @@ -1,70 +0,0 @@ -/** - * vim: set ts=4 : - * =============================================================== - * CS:S DM, Copyright (C) 2004-2007 AlliedModders LLC. - * By David "BAILOPAN" Anderson - * 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 as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Version: $Id$ - */ - -#ifndef _INCLUDE_CSSDM_UTILS_H_ -#define _INCLUDE_CSSDM_UTILS_H_ - -#include "smsdk_ext.h" - -#if defined PLATFORM_POSIX -#define EXTRA_VTBL_OFFSET 1 -#elif defined PLATFORM_WINDOWS -#define EXTRA_VTBL_OFFSET 0 -#endif - -#define CS_TEAM_T 2 -#define CS_TEAM_CT 3 - -struct dmpatch_t -{ - dmpatch_t() - { - patch[0] = 0; - bytes = 0; - } - unsigned char patch[20]; - size_t bytes; -}; - -/** "Safe" functions */ -CBaseEntity *DM_GetBaseEntity(int index); -void DM_RespawnPlayer(int client); -void DM_RemoveEntity(CBaseEntity *pEntity); -bool DM_IsPlayerAlive(int client); -bool DM_CheckSerial(edict_t *pEdict, int serial); -size_t DM_StringToBytes(const char *str, unsigned char buffer[], size_t maxlength); -void DM_ApplyPatch(void *address, int offset, const dmpatch_t *patch, dmpatch_t *restore); -void DM_RemoveAllItems(CBaseEntity *pEntity, bool removeSuit); -void DM_SetMemPatchable(void *address, size_t size); - -/** "Internal" functions */ -CBaseEntity *DM_GetAndClearRagdoll(CBaseEntity *pEntity, int &serial); - -/** Main functions */ -bool InitializeUtils(char *error, size_t maxlength); -void ShutdownUtils(); - -#endif //_INCLUDE_CSSDM_UTILS_H_ diff --git a/cssdm_version.h b/cssdm_version.h deleted file mode 100644 index 7572945..0000000 --- a/cssdm_version.h +++ /dev/null @@ -1,52 +0,0 @@ -/** - * vim: set ts=4 : - * ============================================================================= - * SourceMod - * 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_CSSDM_VERSION_INFORMATION_H_ -#define _INCLUDE_CSSDM_VERSION_INFORMATION_H_ - -/** - * @file Contains SourceMod version information. - * @brief This file will redirect to an autogenerated version if being compiled via - * the build scripts. - */ - -#if defined CSSDM_GENERATED_BUILD -#include -#else -#define CSSDM_BUILD_STRING "-pdev" -#define CSSDM_BUILD_UNIQUEID "nn:y" CSSDM_BUILD_STRING -#define CSSDM_FULL_VERSION "2.1.5" CSSDM_BUILD_STRING -#define CSSDM_FILE_VERSION 2,1,3,0 -#endif -#define CSSDM_BUILD_TIMESTAMP __DATE__ " " __TIME__ - -#endif /* _INCLUDE_CSSDM_VERSION_INFORMATION_H_ */ - diff --git a/cssdm_weapons.cpp b/cssdm_weapons.cpp deleted file mode 100644 index fe76bca..0000000 --- a/cssdm_weapons.cpp +++ /dev/null @@ -1,131 +0,0 @@ -/** - * vim: set ts=4 : - * =============================================================== - * CS:S DM, Copyright (C) 2004-2007 AlliedModders LLC. - * By David "BAILOPAN" Anderson - * 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 as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Version: $Id$ - */ - -#include -#include -#include -#include "cssdm_weapons.h" -#include "cssdm_headers.h" - -std::unordered_map g_WeaponLookup; -std::vector g_Weapons; - -std::string DM_StringToLower(std::string string) -{ - std::transform(string.begin(), string.end(), string.begin(), [](const unsigned char c) - { - return static_cast(std::tolower(c)); - }); - return string; -} - -dm_weapon_t* DM_FindWeapon(std::string_view name) -{ - if (!g_WeaponLookup.contains(name.data())) - { - return nullptr; - } - - return &g_WeaponLookup[std::string(name)]; -} - -dm_weapon_t* DM_GetWeapon(unsigned int index) -{ - if (index >= g_Weapons.size()) - { - return nullptr; - } - - return &g_Weapons[index]; -} - -bool DM_ParseWeapons(char *error, size_t maxlength) -{ - char path[PLATFORM_MAX_PATH]; - g_pSM->BuildPath(Path_Game, path, sizeof(path), "cfg/cssdm/cssdm.weapons.txt"); - - KeyValues *kv = new KeyValues("Weapons"); - if (!kv->LoadFromFile(basefilesystem, path)) - { - kv->deleteThis(); - snprintf(error, maxlength, "Could not load weapons file \"%s\"", path); - return false; - } - - const char *game = g_pSM->GetGameFolderName(); - KeyValues *weapons = kv->FindKey(game, false); - if (!weapons) - { - kv->deleteThis(); - snprintf(error, maxlength, "Could not find \"%s\" section in weapons file", game); - return false; - } - - for (weapons = weapons->GetFirstTrueSubKey(); weapons != NULL; weapons = weapons->GetNextTrueSubKey()) - { - dm_weapon_t wp; - - /* Deal with section name */ - char name[64]; - std::string pName = DM_StringToLower(std::string(weapons->GetName())); - - snprintf(name, sizeof(name), "weapon_%s", pName.c_str()); - wp.classname = std::string(name); - - /* Deal with other strings */ - wp.display = std::string(weapons->GetString("name", pName.c_str())); - - const char *type = weapons->GetString("type", ""); - wp.type = WeaponType::WeaponType_Invalid; - if (strcmp(type, "primary") == 0) - { - wp.type = WeaponType::WeaponType_Primary; - } else if (strcmp(type, "secondary") == 0) { - wp.type = WeaponType::WeaponType_Secondary; - } else if (strcmp(type, "grenade") == 0) { - wp.type = WeaponType::WeaponType_Grenade; - } else if (strcmp(type, "c4") == 0) { - wp.type = WeaponType::WeaponType_C4; - } - - if (wp.type != WeaponType::WeaponType_Invalid) - { - wp.id = static_cast(g_Weapons.size()); - g_WeaponLookup.insert({ pName.c_str(), wp }); - g_Weapons.push_back(wp); - } - } - - kv->deleteThis(); - - return true; -} - -void DM_FreeWeapons() -{ - g_Weapons.clear(); - g_WeaponLookup.clear(); -} diff --git a/cssdm_weapons.h b/cssdm_weapons.h deleted file mode 100644 index 94c1272..0000000 --- a/cssdm_weapons.h +++ /dev/null @@ -1,58 +0,0 @@ -/** - * vim: set ts=4 : - * =============================================================== - * CS:S DM, Copyright (C) 2004-2007 AlliedModders LLC. - * By David "BAILOPAN" Anderson - * 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 as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Version: $Id$ - */ - -#ifndef _INCLUDE_CSSDM_WEAPONS_H_ -#define _INCLUDE_CSSDM_WEAPONS_H_ - -#include -#include - -enum class WeaponType : std::int8_t -{ - WeaponType_Invalid = -1, - WeaponType_Primary = 0, - WeaponType_Secondary = 1, - WeaponType_Grenade = 3, - WeaponType_C4 = 4, -}; - -struct dm_weapon_t -{ - std::string classname; - std::string display; - WeaponType type; - int id; -}; - -/* External API */ -dm_weapon_t* DM_FindWeapon(std::string_view name); -dm_weapon_t* DM_GetWeapon(unsigned int index); - -/* Internal API */ -bool DM_ParseWeapons(char *error, size_t maxlength); -void DM_FreeWeapons(); - -#endif //_INCLUDE_CSSDM_WEAPONS_H_ diff --git a/gamedata/cssdm.games.txt b/gamedata/cssdm.games.txt index 204448f..f88dc28 100644 --- a/gamedata/cssdm.games.txt +++ b/gamedata/cssdm.games.txt @@ -19,37 +19,33 @@ "linux64" "180" } } - "Signatures" - { - // win fcn.1043a0c0 12/25 - "RoundRespawn" - { - "library" "server" - "windows" "\x55\x8B\xEC\x83\xEC\x0C\x53\x56\x57\x8B\xF9\x8B\x0D\x2A\x2A\x2A\x2A\x8B\x01" - "linux" "\x55\x89\xE5\x56\x53\x83\xEC\x1C\x8B\x5D\x08\xFF\x35\x2A\x2A\x2A\x2A\xE8\x2A\x2A\x2A\x2A\x83\xC4\x10\x84\xC0\x0F\x85\x2A\x2A\x2A\x2A\x8B\x13" - "linux64" "\x55\x48\x89\xE5\x41\x57\x41\x56\x41\x55\x41\x54\x53\x48\x89\xFB\x48\x83\xEC\x18\x4C\x8B\x25\x85\x17\xB4\x00" - } - } } "cstrike" { /* FFA patch bytes */ "Keys" { - "LagCompPatch_Windows" "\x90\x90\x90\x90\x90\x90" - "LagCompPatch_Windows64" "\x90\x90" - "LagCompPatch_Linux" "\x90\xE9" - "LagCompPatch_Linux64" "\x90\xE9" - - "TakeDmgPatch1_Windows" "\xEB" - "TakeDmgPatch1_Windows64" "\xEB" - "TakeDmgPatch1_Linux" "\xEB" - "TakeDmgPatch1_Linux64" "\xEB" - - "CalcDomRevPatch_Windows" "\x90\x90\x90\x90\x90\x90" - "CalcDomRevPatch_Windows64" "\x90\x90\x90\x90\x90\x90" - "CalcDomRevPatch_Linux" "\x90\x90\x90\x90\x90\x90" - "CalcDomRevPatch_Linux64" "\x90\x90\x90\x90\x90\x90" + "LagCompPatch" + { + "windows" "\x90\x90\x90\x90\x90\x90" + "windows64" "\x90\x90" + "linux" "\x90\x90\x90\x90\x90\x90" + "linux64" "\x90\x90\x90\x90\x90\x90" + } + "TakeDmgPatch1" + { + "windows" "\xEB" + "windows64" "\xEB" + "linux" "\xEB" + "linux64" "\xEB" + } + "CalcDomRevPatch" + { + "windows" "\x90\x90\x90\x90\x90\x90" + "windows64" "\x90\x90\x90\x90\x90\x90" + "linux" "\x90\xE9" + "linux64" "\x90\xE9" + } } "Offsets" { @@ -100,14 +96,6 @@ } "Signatures" { - "RoundRespawn" - { - "library" "server" - "windows" "\x55\x8B\xEC\x51\x89\x4D\xFC\x8B\x45\xFC\x8B\x10" - "windows64" "\x48\x89\x4C\x24\x08\x48\x83\xEC\x28\x48\x8B\x44\x24\x30\x48\x8B\x00\x48\x8B\x4C\x24\x30" - "linux" "@_ZN9CCSPlayer12RoundRespawnEv" - "linux64" "@_ZN9CCSPlayer12RoundRespawnEv" - } "OnTakeDamage" { "library" "server" @@ -133,5 +121,28 @@ "linux64" "@_ZN12CCSGameStats24CalcDominationAndRevengeEP9CCSPlayerS1_Pi" } } + "Functions" + { + "IPointsForKill" + { + "offset" "IPointsForKill" + "callconv" "thiscall" + "hooktype" "gamerules" + "return" "int" + "this" "ignore" + + "arguments" + { + "pAttacker" + { + "type" "cbaseentity" + } + "pKilled" + { + "type" "cbaseentity" + } + } + } + } } } diff --git a/hl2sdk-manifests b/hl2sdk-manifests deleted file mode 160000 index 4304a88..0000000 --- a/hl2sdk-manifests +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 4304a88cf5cb750d5f694884ad132f82a644542e diff --git a/product.version b/product.version index 1ae3dbd..8395848 100644 --- a/product.version +++ b/product.version @@ -1 +1 @@ -2.1.6-dev \ No newline at end of file +2.1.7-dev diff --git a/scripting/AMBuilder b/scripting/AMBuilder index 7006188..66cd804 100644 --- a/scripting/AMBuilder +++ b/scripting/AMBuilder @@ -2,6 +2,7 @@ import os pluginFiles = [ + 'dm_base.sp', 'dm_basics.sp', 'dm_bot_quotas.sp', 'dm_equipment.sp', diff --git a/scripting/dm_base.sp b/scripting/dm_base.sp new file mode 100644 index 0000000..9fcd92e --- /dev/null +++ b/scripting/dm_base.sp @@ -0,0 +1,669 @@ +/** + * dm_base.sp + * CS:S DM Base. + * This file is part of CS:S DM, Copyright (C) 2005-2007 AlliedModders LLC + * by David "BAILOPAN" Anderson, http://www.bailopan.net/cssdm/ + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Version: $Id$ + */ + +#pragma newdecls required +#pragma semicolon 1 +#include +#include +#include +#include +#include +#undef REQUIRE_PLUGIN +#include +#define REQUIRE_PLUGIN + +bool g_IsCSGO = false; + +enum struct Weapon +{ + char classname[64]; + char display[64]; + DmWeaponType type; + int id; +} + +ArrayList g_Weapons; +StringMap g_WeaponLookup; + +#pragma unused cssdm_version +ConVar cssdm_version; +ConVar cssdm_enabled; +ConVar cssdm_ffa_enabled; +ConVar cssdm_respawn_wait; +ConVar cssdm_ragdoll_time; +ConVar cssdm_spawn_method; + +MemoryPatch g_LagCompPatch = null; +MemoryPatch g_TakeDmgPatch1 = null; +MemoryPatch g_CalcDomRevPatch = null; + +GlobalForward g_StartupForward; +GlobalForward g_ShutdownForward; +GlobalForward g_OnClientSpawnedForward; +GlobalForward g_OnClientPostSpawnedForward; +GlobalForward g_OnClientDeathForward; +GlobalForward g_OnClientSetSpawnMethodForward; + +int g_GameRulesHookID = INVALID_HOOK_ID; +bool g_FFAFailed = false; +bool g_InRoundRestart = false; +bool g_SkipNextPlayerSpawnCallback[MAXPLAYERS] = { false, ... }; +Handle g_PlayerRespawnTimers[MAXPLAYERS] = { null, ... }; + +DynamicHook g_IPointsForKillHook; + +Handle g_RemoveAllItemsSDKCall; + +public Plugin myinfo = +{ + name = "CS:S DM Base", + author = "AlliedModders LLC", + description = "CS:S DM Base", + version = CSSDM_VERSION, + url = "http://www.bailopan.net/cssdm/" +}; + +public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max) +{ + char game[128]; + GetGameFolderName(game, sizeof(game)); + g_IsCSGO = StrEqual(game, "csgo", false); + if (!g_IsCSGO && !StrEqual(game, "cstrike", false)) + { + strcopy(error, err_max, "This plugin will only work on Counter-Strike: Source or Counter-Strike: Global Offensive"); + return APLRes_SilentFailure; + } + + CreateNative("DM_IsRunning", Native_IsRunning); + CreateNative("DM_GetSpawnMethod", Native_GetSpawnMethod); + CreateNative("DM_GetWeaponID", Native_GetWeaponID); + CreateNative("DM_GetWeaponType", Native_GetWeaponType); + CreateNative("DM_GetWeaponClassname", Native_GetWeaponClassname); + CreateNative("DM_GetWeaponName", Native_GetWeaponName); + CreateNative("DM_StripBotItems", Native_StripBotItems); + CreateNative("DM_GetSpawnWaitTime", Native_GetSpawnWaitTime); + CreateNative("DM_RespawnClient", Native_RespawnClient); + + RegPluginLibrary("CS:S DM"); + + return APLRes_Success; +} + +public void OnPluginStart() +{ + g_StartupForward = new GlobalForward("DM_OnStartup", ET_Ignore); + g_ShutdownForward = new GlobalForward("DM_OnShutdown", ET_Ignore); + g_OnClientSpawnedForward = new GlobalForward("DM_OnClientSpawned", ET_Ignore, Param_Cell); + g_OnClientPostSpawnedForward = new GlobalForward("DM_OnClientPostSpawned", ET_Ignore, Param_Cell); + g_OnClientDeathForward = new GlobalForward("DM_OnClientDeath", ET_Hook, Param_Cell); + g_OnClientSetSpawnMethodForward = new GlobalForward("DM_OnSetSpawnMethod", ET_Hook, Param_String); + + cssdm_version = CreateConVar("cssdm_version", CSSDM_VERSION, "CS:S DM Version", FCVAR_NOTIFY); + cssdm_enabled = CreateConVar("cssdm_enabled", "1", "Sets whether CS:S DM is enabled", FCVAR_NOTIFY); + cssdm_enabled.AddChangeHook(OnEnableCvarChanged); + if (!g_IsCSGO) + { + cssdm_enabled.AddChangeHook(OnFFARelatedCvarChanged); + cssdm_ffa_enabled = CreateConVar("cssdm_ffa_enabled", "0", "Sets whether Free-For-All mode is enabled", FCVAR_NOTIFY); + cssdm_ffa_enabled.AddChangeHook(OnFFARelatedCvarChanged); + } + cssdm_respawn_wait = CreateConVar("cssdm_respawn_wait", "0.75", "Sets respawn wait time"); + cssdm_ragdoll_time = CreateConVar("cssdm_ragdoll_time", "2", "Sets ragdoll stay time", _, true, 0.0, true, 20.0); + cssdm_spawn_method = CreateConVar("cssdm_spawn_method", "preset", "Sets how and where players are spawned"); + cssdm_spawn_method.AddChangeHook(OnSpawnMethodChanged); + + g_Weapons = new ArrayList(sizeof(Weapon)); + g_WeaponLookup = new StringMap(); + + char weaponParseError[128]; + if (!ParseWeaponConfig("cfg/cssdm/cssdm.weapons.txt", weaponParseError, sizeof(weaponParseError))) + { + SetFailState(weaponParseError); + } + + GameData gamedata = new GameData("cssdm.games"); + if (gamedata == null) + { + SetFailState("Could not load CSSDM gamedata"); + } + + StartPrepSDKCall(SDKCall_Player); + if (!PrepSDKCall_SetFromConf(gamedata, SDKConf_Virtual, "RemoveAllItems")) + { + delete gamedata; + SetFailState("Could not find offset RemoveAllItems"); + } + PrepSDKCall_AddParameter(SDKType_Bool, SDKPass_ByValue); + g_RemoveAllItemsSDKCall = EndPrepSDKCall(); + + if (!g_IsCSGO) + { + g_IPointsForKillHook = DynamicHook.FromConf(gamedata, "IPointsForKill"); + if (g_IPointsForKillHook == null) + { + delete gamedata; + SetFailState("Could not find offset or function info about IPointsForKill"); + } + + g_LagCompPatch = new MemoryPatch(gamedata, "WantsLagComp", "LagCompPatch", "LagCompPatch"); + g_TakeDmgPatch1 = new MemoryPatch(gamedata, "OnTakeDamage", "TakeDmgPatch1", "TakeDmgPatch1"); + g_CalcDomRevPatch = new MemoryPatch(gamedata, "CalcDominationAndRevenge", "CalcDomRevPatch", "CalcDomRevPatch"); + // FIXME: We use SetFailState in the MemoryPatch constructor for now until there's a better + // way to handle exceptions in class constructors + + // if (g_LagCompPatch == null || g_TakeDmgPatch1 == null || g_CalcDomRevPatch == null) + // { + // LogError("FFA will not work: Failed to create one or more memory patch(es)!"); + // g_FFAFailed = true; + // } + } + + delete gamedata; + + HookEvent("player_death", Event_PlayerDeath); + HookEvent("player_spawn", Event_PlayerSpawn); + HookEvent("round_start", Event_RoundStart, EventHookMode_PostNoCopy); + HookEvent("round_end", Event_RoundEnd, EventHookMode_PostNoCopy); + + AutoExecConfig(false, "cssdm", "cssdm"); +} + +public void OnConfigsExecuted() +{ + if (!cssdm_enabled.BoolValue) + { + return; + } + + char map[128], mapDisplay[128]; + GetCurrentMap(map, sizeof(map)); + GetMapDisplayName(map, mapDisplay, sizeof(mapDisplay)); + + if (strlen(mapDisplay)) + { + ServerCommand("exec cssdm/maps/%s.cssdm.cfg", mapDisplay); + } + + SetupFFA(); + + Call_StartForward(g_StartupForward); + Call_Finish(); +} + +public void OnEnableCvarChanged(ConVar convar, const char[] oldValue, const char[] newValue) +{ + int old = StringToInt(oldValue); + int value = StringToInt(newValue); + if (old == value) + { + return; + } + if (value) + { + Call_StartForward(g_StartupForward); + Call_Finish(); + } + else + { + Call_StartForward(g_ShutdownForward); + Call_Finish(); + } +} + +public void OnFFARelatedCvarChanged(ConVar convar, const char[] oldValue, const char[] newValue) +{ + SetupFFA(); +} + +public void OnSpawnMethodChanged(ConVar convar, const char[] oldValue, const char[] newValue) +{ + bool validMethod = StrEqual(newValue, "preset") || StrEqual(newValue, "none"); + if (!validMethod) + { + LogMessage("Invalid spawn method passed to cssdm_spawn_method, resetting to default"); + } + convar.RestoreDefault(); + char value[64]; + convar.GetString(value, sizeof(value)); + Call_StartForward(g_OnClientSetSpawnMethodForward); + Call_PushString(value); + Call_Finish(); +} + +public void OnClientDisconnect(int client) +{ + KillPlayerRespawnTimer(client); +} + +public void OnMapStart() +{ + ResetSkipSpawnCallback(); + if (!g_IsCSGO) + { + g_GameRulesHookID = g_IPointsForKillHook.HookGamerules(Hook_Pre, Hook_OnIPointsForKill); + if (g_GameRulesHookID == INVALID_HOOK_ID) + { + LogError("FFA will not work: Failed to hook IPointsForKill!"); + } + } +} + +public void OnMapEnd() +{ + ResetSkipSpawnCallback(); + if (!g_IsCSGO && g_GameRulesHookID != INVALID_HOOK_ID) + { + DynamicHook.RemoveHook(g_GameRulesHookID); + } + for (int i = 0; i <= MaxClients; i++) + { + KillPlayerRespawnTimer(i); + } + if (cssdm_enabled.BoolValue) + { + Call_StartForward(g_ShutdownForward); + Call_Finish(); + } +} + +void SetupFFA() +{ + if (g_IsCSGO) + { + return; + } + if (cssdm_enabled.BoolValue && cssdm_ffa_enabled.BoolValue) + { + g_LagCompPatch.Enable(); + g_TakeDmgPatch1.Enable(); + g_CalcDomRevPatch.Enable(); + } + else + { + g_LagCompPatch.Disable(); + g_TakeDmgPatch1.Disable(); + g_CalcDomRevPatch.Disable(); + } +} + +bool ParseWeaponConfig(const char[] configPath, char[] error, int err_max) +{ + char game[128]; + GetGameFolderName(game, sizeof(game)); + StringToLower(game); + + KeyValues kv = new KeyValues("Weapons"); + if (!kv.ImportFromFile(configPath)) + { + delete kv; + Format(error, err_max, "Could not load weapons file \"%s\"", configPath); + return false; + } + + if (!kv.JumpToKey(game)) + { + delete kv; + Format(error, err_max, "Could not find \"%s\" section in weapons file", game); + return false; + } + + if (!kv.GotoFirstSubKey()) + { + delete kv; + strcopy(error, err_max, "No weapons defined for game"); + return false; + } + + int id = 0; + do + { + char name[64], display[64], classname[64], typeStr[32]; + DmWeaponType type = DmWeapon_Invalid; + Weapon weapon; + + kv.GetSectionName(name, sizeof(name)); + StringToLower(name); + + Format(classname, sizeof(classname), "weapon_%s", name); + strcopy(weapon.classname, sizeof(weapon.classname), classname); + kv.GetString("name", display, sizeof(display)); + strcopy(weapon.display, sizeof(weapon.display), display); + kv.GetString("type", typeStr, sizeof(typeStr)); + + if (StrEqual(typeStr, "primary", false)) + { + type = DmWeapon_Primary; + } + else if (StrEqual(typeStr, "secondary", false)) + { + type = DmWeapon_Secondary; + } + else if (StrEqual(typeStr, "grenade", false)) + { + type = DmWeapon_Grenade; + } + else if (StrEqual(typeStr, "c4", false)) + { + type = DmWeapon_C4; + } + weapon.type = type; + + if (type != DmWeapon_Invalid) + { + weapon.id = ++id; + g_WeaponLookup.SetArray(name, weapon, sizeof(weapon)); + g_Weapons.PushArray(weapon); + } + } while (kv.GotoNextKey()); + + delete kv; + return true; +} + +void KillPlayerRespawnTimer(int client) +{ + if (client <= 0) + { + return; + } + if (g_PlayerRespawnTimers[client] != null) + { + delete g_PlayerRespawnTimers[client]; + g_PlayerRespawnTimers[client] = null; + } +} + +void ResetSkipSpawnCallback() +{ + for (int i = 0; i < MAXPLAYERS; i++) + { + g_SkipNextPlayerSpawnCallback[i] = false; + } +} + +// Hooks +public void Event_PlayerDeath(Event event, const char[] name, bool dontBroadcast) +{ + if (!cssdm_enabled.BoolValue) + { + return; + } + + int client = GetClientOfUserId(event.GetInt("userid")); + if (client <= 0 || !IsClientInGame(client)) + { + return; + } + + Call_StartForward(g_OnClientDeathForward); + Call_PushCell(client); + Action forwardResult = Plugin_Continue; + Call_Finish(forwardResult); + + float ragdollStayTime = cssdm_ragdoll_time.FloatValue; + if (ragdollStayTime >= 0.0 && ragdollStayTime <= 20.0) + { + int ragdollEnt = GetEntPropEnt(client, Prop_Send, "m_hRagdoll"); + + if (ragdollEnt != -1 && IsValidEntity(ragdollEnt)) + { + if (ragdollStayTime == 0.0) + { + AcceptEntityInput(ragdollEnt, "Kill"); + } + else + { + int ragdollRef = EntIndexToEntRef(ragdollEnt); + if (ragdollRef != INVALID_ENT_REFERENCE) + { + CreateTimer(ragdollStayTime, Timer_CleanUpRagdoll, ragdollRef); + } + } + } + } + + if (forwardResult == Plugin_Continue) + { + KillPlayerRespawnTimer(client); + g_PlayerRespawnTimers[client] = CreateTimer(cssdm_ragdoll_time.FloatValue, Timer_PlayerRespawn, client); + } +} + +public Action Timer_PlayerRespawn(Handle timer, int client) +{ + if (cssdm_enabled.BoolValue && !g_InRoundRestart && IsClientInGame(client)) + { + CS_RespawnPlayer(client); + } + g_PlayerRespawnTimers[client] = null; + return Plugin_Continue; +} + +public Action Timer_CleanUpRagdoll(Handle timer, int ragdollRef) +{ + if (!cssdm_enabled.BoolValue) + { + return Plugin_Continue; + } + int ent = EntRefToEntIndex(ragdollRef); + if (ent != INVALID_ENT_REFERENCE && IsValidEntity(ent)) + { + AcceptEntityInput(ent, "Kill"); + } + return Plugin_Continue; +} + +public void Event_PlayerSpawn(Event event, const char[] name, bool dontBroadcast) +{ + int client = GetClientOfUserId(event.GetInt("userid")); + if (client <= 0 || !IsClientInGame(client)) + { + return; + } + + if (g_SkipNextPlayerSpawnCallback[client]) + { + g_SkipNextPlayerSpawnCallback[client] = false; + return; + } + + if (!cssdm_enabled.BoolValue || g_InRoundRestart) + { + return; + } + + // IsClientObserver will always return false on css for some reason + int team = GetClientTeam(client); + if (team != CS_TEAM_T && team != CS_TEAM_CT) + { + return; + } + + Call_StartForward(g_OnClientSpawnedForward); + Call_PushCell(client); + Call_Finish(); + Call_StartForward(g_OnClientPostSpawnedForward); + Call_PushCell(client); + Call_Finish(); +} + +public void Event_RoundStart(Event event, const char[] name, bool dontBroadcast) +{ + g_InRoundRestart = false; +} + +public void Event_RoundEnd(Event event, const char[] name, bool dontBroadcast) +{ + g_InRoundRestart = true; + ResetSkipSpawnCallback(); + for (int i = 0; i <= MaxClients; i++) + { + KillPlayerRespawnTimer(i); + } +} + +public MRESReturn Hook_OnIPointsForKill(DHookReturn hReturn, DHookParam hParams) +{ + if (cssdm_enabled.BoolValue && cssdm_ffa_enabled.BoolValue && !g_FFAFailed) + { + hReturn.Value = 1; + return MRES_Supercede; + } + return MRES_Ignored; +} + +// Native callbacks +// native bool DM_IsRunning(); +public int Native_IsRunning(Handle plugin, int numParams) +{ + return view_as(cssdm_enabled.BoolValue); +} + +// native void DM_GetSpawnMethod(char[] method, int maxlength); +public void Native_GetSpawnMethod(Handle plugin, int numParams) +{ + char spawnMethod[32]; + cssdm_spawn_method.GetString(spawnMethod, sizeof(spawnMethod)); + SetNativeString(1, spawnMethod, GetNativeCell(2)); +} + +// native int DM_GetWeaponID(const char[] name); +public int Native_GetWeaponID(Handle plugin, int numParams) +{ + char name[64]; + GetNativeString(1, name, sizeof(name)); + Weapon weapon; + if (!g_WeaponLookup.GetArray(name, weapon, sizeof(weapon))) + { + return -1; + } + return weapon.id; +} + +// native DmWeaponType DM_GetWeaponType(int index); +public int Native_GetWeaponType(Handle plugin, int numParams) +{ + int id = GetNativeCell(1); + Weapon weapon; + if (id >= g_Weapons.Length) + { + return ThrowNativeError(SP_ERROR_NATIVE, "Invalid CS:S DM weapon id (%d)", id); + } + g_Weapons.GetArray(id, weapon, sizeof(weapon)); + return view_as(weapon.type); +} + +// native void DM_GetWeaponClassname(int id, char[] classname, int maxlength); +public int Native_GetWeaponClassname(Handle plugin, int numParams) +{ + int id = GetNativeCell(1); + Weapon weapon; + if (id >= g_Weapons.Length) + { + return ThrowNativeError(SP_ERROR_NATIVE, "Invalid CS:S DM weapon id (%d)", id); + } + g_Weapons.GetArray(id, weapon, sizeof(weapon)); + SetNativeString(2, weapon.classname, GetNativeCell(3)); + return 1; +} + +// native void DM_GetWeaponName(int id, char[] name, int maxlength); +public int Native_GetWeaponName(Handle plugin, int numParams) +{ + int id = GetNativeCell(1); + Weapon weapon; + if (id >= g_Weapons.Length) + { + return ThrowNativeError(SP_ERROR_NATIVE, "Invalid CS:S DM weapon id (%d)", id); + } + g_Weapons.GetArray(id, weapon, sizeof(weapon)); + SetNativeString(2, weapon.display, GetNativeCell(3)); + return 1; +} + +// native void DM_StripBotItems(int client); +public int Native_StripBotItems(Handle plugin, int numParams) +{ + int client = GetNativeCell(1); + + if (client <= 0 || client > MaxClients) + { + return ThrowNativeError(SP_ERROR_NATIVE, "Invalid client index %d", client); + } + + if (!IsClientInGame(client)) + { + return ThrowNativeError(SP_ERROR_NATIVE, "Client %d is not in game", client); + } + + if (!IsFakeClient(client)) + { + return ThrowNativeError(SP_ERROR_NATIVE, "Client %d is not a bot", client); + } + + SDKCall(g_RemoveAllItemsSDKCall, client, false); + + return 1; +} + +// native float DM_GetSpawnWaitTime(); +public any Native_GetSpawnWaitTime(Handle plugin, int numParams) +{ + return cssdm_respawn_wait.FloatValue; +} + +// native void DM_RespawnClient(int client, bool fullRespawn=true); +public int Native_RespawnClient(Handle plugin, int numParams) +{ + int client = GetNativeCell(1); + + if (client <= 0 || client > MaxClients) + { + return ThrowNativeError(SP_ERROR_NATIVE, "Invalid client index %d", client); + } + + if (!IsClientInGame(client)) + { + return ThrowNativeError(SP_ERROR_NATIVE, "Client %d is not in game", client); + } + + // hopefully this won't cause some race condition + bool fullRespawn = GetNativeCell(2); + if (!fullRespawn) + { + g_SkipNextPlayerSpawnCallback[client] = true; + } + + CS_RespawnPlayer(client); + + return 1; +} + +// Utils +void StringToLower(char[] str) +{ + for (int i = 0; str[i] != '\0'; i++) + { + str[i] = CharToLower(str[i]); + } +} diff --git a/scripting/dm_preset_spawns.sp b/scripting/dm_preset_spawns.sp index ca55f47..038d6c5 100644 --- a/scripting/dm_preset_spawns.sp +++ b/scripting/dm_preset_spawns.sp @@ -44,20 +44,25 @@ float g_SpawnOrigins[MAX_SPAWNS][3]; float g_SpawnAngles[MAX_SPAWNS][3]; Menu g_hSpawnMenu; int g_LastLocation[MAXPLAYERS+1]; +ConVar cssdm_enable_spawn_editor; public void OnPluginStart() { + LoadTranslations("common.phrases"); + LoadTranslations("cssdm_spawn_editor.phrases"); + + cssdm_enable_spawn_editor = CreateConVar("cssdm_enable_spawn_editor", "0", "Enables the spawn editor"); RegAdminCmd("cssdm_spawn_menu", Command_SpawnMenu, ADMFLAG_CHANGEMAP, "Edits CS:S DM spawn points"); - g_hSpawnMenu = new Menu(Menu_EditSpawns); - g_hSpawnMenu.SetTitle("Spawn Point Editor"); - g_hSpawnMenu.AddItem("nearest", "Teleport to nearest"); - g_hSpawnMenu.AddItem("previous", "Teleport to previous"); - g_hSpawnMenu.AddItem("next", "Teleport to next"); - g_hSpawnMenu.AddItem("add", "Add position"); - g_hSpawnMenu.AddItem("preinsert", "Insert position here"); - g_hSpawnMenu.AddItem("delete", "Delete nearest"); - g_hSpawnMenu.AddItem("clear", "Delete all"); + g_hSpawnMenu = new Menu(Menu_EditSpawns, MENU_ACTIONS_DEFAULT | MenuAction_Display | MenuAction_DisplayItem); + g_hSpawnMenu.SetTitle("Spawn Point Editor Title"); + g_hSpawnMenu.AddItem("nearest", "Teleport Nearest"); + g_hSpawnMenu.AddItem("previous", "Teleport Previous"); + g_hSpawnMenu.AddItem("next", "Teleport Next"); + g_hSpawnMenu.AddItem("add", "Add Position"); + g_hSpawnMenu.AddItem("preinsert", "Insert Position"); + g_hSpawnMenu.AddItem("delete", "Delete Nearest"); + g_hSpawnMenu.AddItem("clear", "Delete All"); } public void OnClientPutInServer(int client) @@ -258,9 +263,14 @@ bool DeleteSpawn(int index) public Action Command_SpawnMenu(int client, int args) { + if (!cssdm_enable_spawn_editor.BoolValue) + { + ReplyToCommand(client, "[CSSDM] %t", "Spawn Editor Disabled"); + return Plugin_Handled; + } if (client == 0) { - ReplyToCommand(client, "[CSSDM] This command is not available from the server console."); + ReplyToCommand(client, "[CSSDM] %t", "Spawn Editor Not Available"); return Plugin_Handled; } @@ -278,34 +288,50 @@ public void Panel_VerifyDeleteSpawns(Menu menu, MenuAction action, int param1, i g_SpawnCount = 0; if (!WriteMapConfig()) { - PrintToChat(param1, "[CSSDM] Could not write to spawn config file."); + PrintToChat(param1, "[CSSDM] %t", "Spawn Editor Config Read Only"); } else { - PrintToChat(param1, "[CSSDM] All spawn points have been deleted."); + PrintToChat(param1, "[CSSDM] %t", "Spawn Editor Deleted All"); } } g_hSpawnMenu.Display(param1, MENU_TIME_FOREVER); } } -public void Menu_EditSpawns(Menu menu, MenuAction action, int param1, int param2) +public int Menu_EditSpawns(Menu menu, MenuAction action, int param1, int param2) { - if (action == MenuAction_Select) + if (action == MenuAction_Display) + { + char title[128], translated[128]; + menu.GetTitle(title, sizeof(title)); + + Panel panel = view_as(param2); + Format(translated, sizeof(translated), "%T", title, param1); + panel.SetTitle(translated); + } + else if (action == MenuAction_DisplayItem) + { + char display[128], translated[128]; + menu.GetItem(param2, "", 0, _, display, sizeof(display)); + Format(translated, sizeof(translated), "%T", display, param1); + return RedrawMenuItem(translated); + } + else if (action == MenuAction_Select) { if (param2 == 0) { int index = GetNearestSpawn(param1); if (index == -1) { - PrintToChat(param1, "[CSSDM] There are no spawn points."); + PrintToChat(param1, "[CSSDM] %t", "Spawn Editor No Spawn Points"); } else { TeleportEntity(param1, g_SpawnOrigins[index], g_SpawnAngles[index], NULL_VECTOR); - PrintToChat(param1, "[CSSDM] Teleported to spawn #%d (%d total).", index, g_SpawnCount); + PrintToChat(param1, "[CSSDM] %t", "Spawn Editor Teleported To Spawn", index, g_SpawnCount); g_LastLocation[param1] = index; } } else if (param2 == 2) { if (g_SpawnCount == 0) { - PrintToChat(param1, "[CSSDM] There are no spawn points."); + PrintToChat(param1, "[CSSDM] %t", "Spawn Editor No Spawn Points"); } else { int index = g_LastLocation[param1] + 1; if (index >= g_SpawnCount) @@ -313,13 +339,13 @@ public void Menu_EditSpawns(Menu menu, MenuAction action, int param1, int param2 index = 0; } TeleportEntity(param1, g_SpawnOrigins[index], g_SpawnAngles[index], NULL_VECTOR); - PrintToChat(param1, "[CSSDM] Teleported to spawn #%d (%d total).", index, g_SpawnCount); + PrintToChat(param1, "[CSSDM] %t", "Spawn Editor Teleported To Spawn", index, g_SpawnCount); g_LastLocation[param1] = index; } } else if (param2 == 1) { if (g_SpawnCount == 0) { - PrintToChat(param1, "[CSSDM] There are no spawn points."); + PrintToChat(param1, "[CSSDM] %t", "Spawn Editor No Spawn Points"); } else { int index = g_LastLocation[param1] - 1; if (index < 0) @@ -327,24 +353,24 @@ public void Menu_EditSpawns(Menu menu, MenuAction action, int param1, int param2 index = g_SpawnCount - 1; } TeleportEntity(param1, g_SpawnOrigins[index], g_SpawnAngles[index], NULL_VECTOR); - PrintToChat(param1, "[CSSDM] Teleported to spawn #%d (%d total).", index, g_SpawnCount); + PrintToChat(param1, "[CSSDM] %t", "Spawn Editor Teleported To Spawn", index, g_SpawnCount); g_LastLocation[param1] = index; } } else if (param2 == 5) { int index = GetNearestSpawn(param1); if (index == -1) { - PrintToChat(param1, "[CSSDM] There are no spawn points."); + PrintToChat(param1, "[CSSDM] %t", "Spawn Editor No Spawn Points"); } else { if (!DeleteSpawn(index)) { - PrintToChat(param1, "[CSSDM] Could not delete spawn #%d.", index); + PrintToChat(param1, "[CSSDM] %t", "Spawn Editor Could Not Delete Spawn", index); } else { if (!WriteMapConfig()) { - PrintToChat(param1, "[CSSDM] Could not write to spawn config file!"); + PrintToChat(param1, "[CSSDM] %t", "Spawn Editor Config Read Only"); } else { - PrintToChat(param1, "[CSSDM] Deleted spawn #%d (%d total).", index, g_SpawnCount); + PrintToChat(param1, "[CSSDM] %t", "Spawn Editor Deleted Spawn", index, g_SpawnCount); } } } @@ -352,13 +378,13 @@ public void Menu_EditSpawns(Menu menu, MenuAction action, int param1, int param2 int index; if ((index = AddSpawnFromClient(param1)) == -1) { - PrintToChat(param1, "[CSSDM] Could not add spawn (max limit reached)."); + PrintToChat(param1, "[CSSDM] %t", "Spawn Editor Max Spawn Points Reached"); } else { if (!WriteMapConfig()) { - PrintToChat(param1, "[CSSDM] Could not write to spawn config file!"); + PrintToChat(param1, "[CSSDM] %t", "Spawn Editor Config Read Only"); } else { - PrintToChat(param1, "[CSSDM] Added spawn #%d (%d total).", index, g_SpawnCount); + PrintToChat(param1, "[CSSDM] %t", "Spawn Editor Added Spawn", index, g_SpawnCount); } } } else if (param2 == 4) { @@ -371,11 +397,11 @@ public void Menu_EditSpawns(Menu menu, MenuAction action, int param1, int param2 } if ((index = InsertSpawnFromClient(param1, pre, index)) == -1) { - PrintToChat(param1, "[CSSDM] Could not add spawn (max limit reached)."); + PrintToChat(param1, "[CSSDM] %t", "Spawn Editor Max Spawn Points Reached"); } else { if (!WriteMapConfig()) { - PrintToChat(param1, "[CSSDM] Could not write to spawn config file!"); + PrintToChat(param1, "[CSSDM] %t", "Spawn Editor Config Read Only"); } else { PrintToChat(param1, "[CSSDM] Inserted spawn at #%d (%d total).", index, g_SpawnCount); } @@ -383,16 +409,22 @@ public void Menu_EditSpawns(Menu menu, MenuAction action, int param1, int param2 } else if (param2 == 6) { /* Of course, we ask the user first. */ Panel panel = new Panel(); - panel.SetTitle("Delete all spawn points?"); - panel.DrawItem("Yes"); - panel.DrawItem("No"); + char title[128], yes[64], no[64]; + Format(title, sizeof(title), "%T", "Spawn Editor Delete All Spawn Points", param1); + Format(yes, sizeof(yes), "%T", "Yes", param1); + Format(no, sizeof(no), "%T", "No", param1); + panel.SetTitle(title); + panel.DrawItem(yes); + panel.DrawItem(no); panel.Send(param1, Panel_VerifyDeleteSpawns, MENU_TIME_FOREVER); delete panel; - return; + return 0; } /* Redraw the menu */ g_hSpawnMenu.Display(param1, MENU_TIME_FOREVER); } + + return 0; } public void DM_OnStartup() @@ -436,7 +468,7 @@ public void DM_OnClientSpawned(int client) int startPoint = GetRandomInt(0, g_SpawnCount-1); /* Prefetch player origins */ - float origins[65][3]; + float origins[MAXPLAYERS + 1][3]; int numToCheck = 0; for (int i=1; i<=MaxClients; i++) diff --git a/scripting/include/cssdm.inc b/scripting/include/cssdm.inc index 2179a25..4765038 100644 --- a/scripting/include/cssdm.inc +++ b/scripting/include/cssdm.inc @@ -18,7 +18,7 @@ #endif #define _cssdm_included -#define CSSDM_VERSION "2.1.6-dev" +#define CSSDM_VERSION "2.1.7-dev" #define CSSDM_MAX_WEAPONS 32 @@ -222,7 +222,20 @@ native void DM_RespawnClient(int client, bool fullRespawn=true); * @return True if alive, false if dead. * @error Invalid client index or client not in game. */ -native bool DM_IsClientAlive(int client); +stock bool DM_IsClientAlive(int client) +{ + if (client <= 0 || client > MaxClients) + { + ThrowError("Invalid client index %d", client); + } + + if (!IsClientInGame(client)) + { + ThrowError("Client %d is not in game", client); + } + + return IsPlayerAlive(client); +} /** * Gives ammo to a player. @@ -252,18 +265,28 @@ stock int DM_GiveClientAmmo(int client, int type, int count, bool noSound=false) /** * Do not edit below this line! */ -public Extension __ext_cssdm = +public SharedPlugin __pl_cssdm = { name = "CS:S DM", - file = "cssdm.ext", -#if defined AUTOLOAD_EXTENSIONS - autoload = 1, -#else - autoload = 0, -#endif -#if defined REQUIRE_EXTENSIONS + file = "dm_base.smx", +#if defined REQUIRE_PLUGIN required = 1, #else required = 0, #endif }; + +#if !defined REQUIRE_PLUGIN +public void __pl_cssdm_SetNTVOptional() +{ + MarkNativeAsOptional("DM_IsRunning"); + MarkNativeAsOptional("DM_GetSpawnMethod"); + MarkNativeAsOptional("DM_GetWeaponID"); + MarkNativeAsOptional("DM_GetWeaponType"); + MarkNativeAsOptional("DM_GetWeaponClassname"); + MarkNativeAsOptional("DM_GetWeaponName"); + MarkNativeAsOptional("DM_StripBotItems"); + MarkNativeAsOptional("DM_GetSpawnWaitTime"); + MarkNativeAsOptional("DM_RespawnClient"); +} +#endif diff --git a/scripting/include/memorypatch.inc b/scripting/include/memorypatch.inc new file mode 100644 index 0000000..ae5dc54 --- /dev/null +++ b/scripting/include/memorypatch.inc @@ -0,0 +1,96 @@ +#include + +#define PATCH_MAX_BYTES 64 +#define PATCH_BYTE_LEN 3 +#define PATCH_BYTE_SPLIT "\\x" +#define PATCH_BYTE_SPLIT_LEN 2 + +class MemoryPatch +{ + private bool _enabled; + private Address _address; + private int _offset; + private int[] _payload; + private int[] _restore; + + MemoryPatch(GameData gamedata, const char[] addressKey, const char[] patchKey, const char[] offsetKey) + { + if (gamedata == null) + { + SetFailState("Provided gamedata is null") + } + + this._address = gamedata.GetMemSig(addressKey); + if (this._address == Address_Null) + { + SetFailState("FFA will not work: Could not find \"%s\" signature!", addressKey); + } + + this._offset = gamedata.GetOffset(offsetKey); + if (this._offset == -1) + { + SetFailState("FFA will not work: Could not find \"%s\" offset!", offsetKey); + } + + char bytesBuffer[PATCH_MAX_BYTES * PATCH_BYTE_SPLIT_LEN * PATCH_BYTE_LEN + 1], + bytes[PATCH_MAX_BYTES][PATCH_BYTE_LEN]; + if (!gamedata.GetKeyValue(patchKey, bytesBuffer, sizeof(bytesBuffer))) + { + SetFailState("FFA will not work: Could not load \"%s\" memory patch!", patchKey); + } + + let payloadLen = ExplodeString(bytesBuffer, PATCH_BYTE_SPLIT, bytes, PATCH_MAX_BYTES, PATCH_BYTE_LEN) - 1; + + this._payload = new int[payloadLen]; + this._restore = new int[payloadLen]; + + let baseAddress = this._address + this._offset; + for (let i = 0; i < payloadLen; i++) + { + this._payload[i] = StringToInt(bytes[i + 1], 16); + this._restore[i] = LoadFromAddress(baseAddress + i, NumberType_Int8); + } + } + + public bool Enable() + { + if (this._enabled) + { + return false; + } + + let baseAddress = this._address + this._offset; + for (let i = 0; i < this._payload.size; i++) + { + StoreToAddress(baseAddress + i, this._payload[i], NumberType_Int8); + } + this._enabled = true; + + return true; + } + + public bool Disable() + { + if (!this._enabled) + { + return false; + } + + let baseAddress = this._address + this._offset; + for (let i = 0; i < this._restore.size; i++) + { + StoreToAddress(baseAddress + i, this._restore[i], NumberType_Int8); + } + this._enabled = false; + + return true; + } + + property bool Enabled + { + get() + { + return this._enabled; + } + } +} diff --git a/sdk/smsdk_config.h b/sdk/smsdk_config.h deleted file mode 100644 index 509e5dd..0000000 --- a/sdk/smsdk_config.h +++ /dev/null @@ -1,58 +0,0 @@ -/** - * vim: set ts=4 : - * =============================================================== - * SourceMod, Copyright (C) 2004-2007 AlliedModders LLC. - * All rights reserved. - * =============================================================== - * - * This file is part of the SourceMod/SourcePawn SDK. This file may only be - * used or modified under the Terms and Conditions of its License Agreement, - * which is found in public/licenses/LICENSE.txt. As of this notice, derivative - * works must be licensed under the GNU General Public License (version 2 or - * greater). A copy of the GPL is included under public/licenses/GPL.txt. - * - * To view the latest information, see: http://www.sourcemod.net/license.php - * - * Version: $Id$ - */ - -#ifndef _INCLUDE_SOURCEMOD_EXTENSION_CONFIG_H_ -#define _INCLUDE_SOURCEMOD_EXTENSION_CONFIG_H_ - -/** - * @file smsdk_config.h - * @brief Contains macros for configuring basic extension information. - */ - -/* Basic information exposed publicly */ -#define SMEXT_CONF_NAME "CS:S DM" -#define SMEXT_CONF_DESCRIPTION "Deathmatch for CS:S" -#define SMEXT_CONF_VERSION "2.1.2" -#define SMEXT_CONF_AUTHOR "AlliedModders" -#define SMEXT_CONF_URL "http://www.bailopan.net/cssdm/" -#define SMEXT_CONF_LOGTAG "CSSDM" -#define SMEXT_CONF_LICENSE "GPL" -#define SMEXT_CONF_DATESTRING __DATE__ - -/** - * @brief Exposes plugin's main interface. - */ -#define SMEXT_LINK(name) SDKExtension *g_pExtensionIface = name; - -/** - * @brief Sets whether or not this plugin required Metamod. - * NOTE: Uncomment to enable, comment to disable. - */ -#define SMEXT_CONF_METAMOD - -/** Enable interfaces you want to use here by uncommenting lines */ -#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 - -#endif // _INCLUDE_SOURCEMOD_EXTENSION_CONFIG_H_ diff --git a/translations/cssdm_spawn_editor.phrases.txt b/translations/cssdm_spawn_editor.phrases.txt new file mode 100644 index 0000000..9a7acd8 --- /dev/null +++ b/translations/cssdm_spawn_editor.phrases.txt @@ -0,0 +1,101 @@ +"Phrases" +{ + "Spawn Point Editor Title" + { + "en" "Spawn Point Editor" + } + + "Teleport Nearest" + { + "en" "Teleport to nearest" + } + + "Teleport Previous" + { + "en" "Teleport to previous" + } + + "Teleport Next" + { + "en" "Teleport to next" + } + + "Add Position" + { + "en" "Add position" + } + + "Insert Position" + { + "en" "Insert position here" + } + + "Delete Nearest" + { + "en" "Delete nearest" + } + + "Delete All" + { + "en" "Delete all" + } + + "Spawn Editor Disabled" + { + "en" "The spawn editor is not enabled." + } + + "Spawn Editor Not Available" + { + "en" "This command is not available from the server console." + } + + "Spawn Editor Config Read Only" + { + "en" "Could not write to spawn config file!" + } + + "Spawn Editor Deleted All" + { + "en" "All spawn points have been deleted." + } + + "Spawn Editor No Spawn Points" + { + "en" "There are no spawn points." + } + + "Spawn Editor Max Spawn Points Reached" + { + "en" "Could not add spawn (max limit reached)." + } + + "Spawn Editor Teleported To Spawn" + { + "#format" "{1:d},{2:d}" + "en" "Teleported to spawn #{1} ({2} total)." + } + + "Spawn Editor Added Spawn" + { + "#format" "{1:d},{2:d}" + "en" "Added spawn #{1} ({2} total)." + } + + "Spawn Editor Deleted Spawn" + { + "#format" "{1:d},{2:d}" + "en" "Deleted spawn #{1} ({2} total)." + } + + "Spawn Editor Could Not Delete Spawn" + { + "#format" "{1:d}" + "en" "Could not delete spawn #{1}." + } + + "Spawn Editor Delete All Spawn Points" + { + "en" "Delete all spawn points?" + } +} diff --git a/version.rc b/version.rc deleted file mode 100644 index 0171ba4..0000000 --- a/version.rc +++ /dev/null @@ -1,103 +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 CSSDM_FILE_VERSION - PRODUCTVERSION CSSDM_FILE_VERSION - 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", "CS:S DM" - VALUE "FileDescription", "CS:S DM" - VALUE "FileVersion", CSSDM_FULL_VERSION - VALUE "InternalName", "cssdm" - VALUE "LegalCopyright", "Copyright (c) 2004-2026, AlliedModders LLC and David 'BAILOPAN' Anderson" - VALUE "OriginalFilename", "cssdm.ext.dll" - VALUE "ProductName", "CS:S DM" - VALUE "ProductVersion", CSSDM_FULL_VERSION - 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 -