diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 37bd39cf..130a767c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -5,16 +5,18 @@ on: branches: [master] paths-ignore: - '**.md' + - '.github/**' pull_request: types: [opened, reopened, synchronize] release: types: [published] + workflow_dispatch: jobs: windows: name: 'Windows' - runs-on: windows-2019 + runs-on: windows-2025 env: solution: 'msvc/reapi.sln' @@ -32,12 +34,52 @@ jobs: - name: Setup MSBuild uses: microsoft/setup-msbuild@v2 - with: - vs-version: '16' +# TODO: add support of 141_xp toolchain at VS2022+ +# - name: Install v140, v141 and v142 toolsets +# shell: cmd +# run: | +# "C:\Program Files (x86)\Microsoft Visual Studio\Installer\vs_installer.exe" modify ^ +# --installPath "C:\Program Files\Microsoft Visual Studio\2022\Enterprise" ^ +# --add Microsoft.VisualStudio.Component.WindowsXP ^ +# --add Microsoft.VisualStudio.Component.VC.v140 ^ +# --add Microsoft.VisualStudio.Component.VC.v140.x86.x64 ^ +# --add Microsoft.VisualStudio.Component.VC.v140.xp ^ +# --add Microsoft.VisualStudio.Component.VC.140.CRT ^ +# --add Microsoft.VisualStudio.Component.VC.v141 ^ +# --add Microsoft.VisualStudio.Component.VC.v141.x86.x64 ^ +# --add Microsoft.VisualStudio.Component.VC.v141.xp ^ +# --add Microsoft.VisualStudio.Component.VC.v142 ^ +# --add Microsoft.VisualStudio.Component.VC.v142.x86.x64 ^ +# --quiet --norestart + + - name: Select PlatformToolset + id: select_toolset + shell: pwsh + run: | + $vswhere = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" + $vs2019 = & $vswhere -products * -version "[16.0,17.0)" -property installationPath -latest + $vs2022 = & $vswhere -products * -version "[17.0,)" -property installationPath -latest + + if ($vs2019) { + "toolset=v140_xp" >> $env:GITHUB_OUTPUT + Write-Host "Selected v140_xp toolset" + } elseif ($vs2022) { + "toolset=v143" >> $env:GITHUB_OUTPUT + Write-Host "Selected v143 toolset" + } else { + Write-Error "No suitable Visual Studio installation found" + exit 1 + } - name: Build run: | - msbuild ${{ env.solution }} -p:Configuration="${{ env.buildRelease }}" /t:Clean,Build /p:Platform=${{ env.buildPlatform }} /p:PlatformToolset=v140_xp /p:XPDeprecationWarning=false + $toolset = '${{ steps.select_toolset.outputs.toolset }}' + msbuild ${{ env.solution }} -p:Configuration="${{ env.buildRelease }}" /t:Clean,Build /p:Platform=${{ env.buildPlatform }} /p:PlatformToolset=$toolset /p:XPDeprecationWarning=false + + - name: Get rcedit from chocolatey + shell: pwsh + run: | + choco install rcedit -y - name: Move files run: | @@ -47,6 +89,49 @@ jobs: move msvc\${{ env.buildRelease }}\reapi_amxx.dll publish\addons\amxmodx\modules\reapi_amxx.dll move msvc\${{ env.buildRelease }}\reapi_amxx.pdb publish\debug\reapi_amxx.pdb + - name: Get app version + id: get_version + shell: pwsh + run: | + $versionFile = "reapi/version/appversion.h" + if (-not (Test-Path $versionFile)) { + Write-Error "Version file not found: $versionFile" + exit 1 + } + + $content = Get-Content $versionFile + foreach ($line in $content) { + if ($line -match '^\s*#define\s+APP_VERSION\s+"([^"]+)"') { + $version = $matches[1] + "version=$version" >> $env:GITHUB_OUTPUT + Write-Host "Found version: $version" + exit 0 + } + } + Write-Error "APP_VERSION not found in file" + exit 1 + + - name: Show version + run: echo "Version is ${{ steps.get_version.outputs.version }}" + + - name: Edit resources at windows binaries + run: | + rcedit ${{ github.workspace }}\publish\addons\amxmodx\modules\reapi_amxx.dll --set-version-string CompanyName "ReHLDS Dev Team" --set-version-string LegalCopyright "Copyright 2025 ReHLDS DevTeam" --set-icon reapi/msvc/icon.ico + shell: "pwsh" + + - name: Import PFX and sign + if: github.event_name != 'pull_request' + env: + KEY_PFX_PASS: ${{ secrets.KEY_PFX_PASS }} + # https://github.com/actions/runner-images/blob/main/images/windows/Windows2025-Readme.md + run: | + $pfxBase64 = "${{ secrets.KEY_PFX_B64 }}" + [IO.File]::WriteAllBytes("${{ github.workspace }}\signing-cert.pfx", [Convert]::FromBase64String($pfxBase64)) + certutil -f -p "${{ secrets.KEY_PFX_PASS }}" -importPFX "${{ github.workspace }}\signing-cert.pfx" + & 'C:\Program Files (x86)\Windows Kits\10\bin\10.0.26100.0\x86\signtool.exe' sign /a /f "${{ github.workspace }}\signing-cert.pfx" /p $env:KEY_PFX_PASS /d "ReAPI - AMX Mod X module, using API regamedll & rehlds" /du "https://rehlds.dev/" /tr "http://timestamp.digicert.com" /td sha256 /fd sha256 /v ${{ github.workspace }}\publish\addons\amxmodx\modules\reapi_amxx.dll + Remove-Item -Recurse -Force "${{ github.workspace }}\signing-cert.pfx" + shell: "pwsh" + - name: Deploy artifacts uses: actions/upload-artifact@v4 with: @@ -80,6 +165,49 @@ jobs: with: fetch-depth: 0 + - name: GPG Import + run: | + echo "${{ secrets.PUB_ASC }}" > "${{ secrets.PUB_ASC_FILE }}" + echo "${{ secrets.KEY_ASC }}" > "${{ secrets.KEY_ASC_FILE }}" + + # Import the public key + gpg --batch --yes --import "${{ secrets.PUB_ASC_FILE }}" + if [[ $? -ne 0 ]]; then + echo "Error: Failed to import the public key" + exit 1 + fi + + # Import the private key + gpg --batch --yes --import "${{ secrets.KEY_ASC_FILE }}" + if [[ $? -ne 0 ]]; then + echo "Error: Failed to import the private key" + exit 2 + fi + + # Extract the fingerprint of the imported public key + GPG_LINUX_FINGERPRINT=$(gpg --list-keys --with-colons | grep '^fpr' | head -n 1 | cut -d: -f10) + + # Check if the fingerprint was extracted + if [[ -z "$GPG_LINUX_FINGERPRINT" ]]; then + echo "Error: Failed to extract the fingerprint of the key" + exit 3 + fi + + # Set the trust level for the key + echo "$GPG_LINUX_FINGERPRINT:6:" | gpg --batch --import-ownertrust + if [ $? -ne 0 ]; then + echo "Error: Failed to set trust for the key $GPG_LINUX_FINGERPRINT" + exit 4 + fi + + echo "Key $GPG_LINUX_FINGERPRINT successfully imported and trusted" + gpg --list-keys + + #export for global use + echo "GPG_LINUX_FINGERPRINT=$GPG_LINUX_FINGERPRINT" >> $GITHUB_ENV + shell: bash + if: github.event_name != 'pull_request' + - name: Build run: | rm -rf build && CC=gcc CXX=g++ cmake -B build && cmake --build build -j8 @@ -94,6 +222,7 @@ jobs: else # Remove quotes APP_VERSION=$(echo $APP_VERSION | xargs) + echo "APP_VERSION=${APP_VERSION}" >> $GITHUB_ENV fi fi echo "version=${APP_VERSION}" >> "$GITHUB_OUTPUT" @@ -150,7 +279,29 @@ jobs: github.event.action == 'published' && startsWith(github.ref, 'refs/tags/') run: | + + # new runner, niw signs + echo "${{ secrets.PUB_ASC }}" > "${{ secrets.PUB_ASC_FILE }}" + echo "${{ secrets.KEY_ASC }}" > "${{ secrets.KEY_ASC_FILE }}" + gpg --batch --yes --import "${{ secrets.PUB_ASC_FILE }}" + gpg --batch --yes --import "${{ secrets.KEY_ASC_FILE }}" + GPG_LINUX_FINGERPRINT=$(gpg --list-keys --with-colons | grep '^fpr' | head -n 1 | cut -d: -f10) + echo "$GPG_LINUX_FINGERPRINT:6:" | gpg --batch --import-ownertrust + echo "GPG_LINUX_FINGERPRINT=$GPG_LINUX_FINGERPRINT" >> $GITHUB_ENV + + sign_file() { + local file=$1 + gpg --batch --yes --detach-sign --armor -u "$GPG_LINUX_FINGERPRINT" "$file" + if [ $? -ne 0 ]; then + echo "Error: Failed to sign $file" + exit 2 + fi + echo "$file signed successfully." + } + + # Pack and sign final archive 7z a -tzip reapi-bin-${{ needs.linux.outputs.app-version }}.zip addons/ + sign_file "reapi-bin-${{ env.APP_VERSION }}.zip" - name: Publish artifacts uses: softprops/action-gh-release@v2 @@ -161,5 +312,7 @@ jobs: with: files: | *.zip + *.7z + *.asc env: GITHUB_TOKEN: ${{ secrets.API_TOKEN }} diff --git a/reapi/extra/amxmodx/scripting/include/cssdk_const.inc b/reapi/extra/amxmodx/scripting/include/cssdk_const.inc index 01afb258..844f0a08 100644 --- a/reapi/extra/amxmodx/scripting/include/cssdk_const.inc +++ b/reapi/extra/amxmodx/scripting/include/cssdk_const.inc @@ -147,35 +147,36 @@ /** * Break Model Defines */ -#define BREAK_TYPEMASK 0x4F #define BREAK_GLASS 0x01 #define BREAK_METAL 0x02 #define BREAK_FLESH 0x04 #define BREAK_WOOD 0x08 -#define BREAK_SMOKE 0x10 -#define BREAK_TRANS 0x20 +#define BREAK_SMOKE 0x10 // generates black floating particles from shards +#define BREAK_TRANS 0x20 // transparent shard flag (use with any of BREAK_TYPEMASK) #define BREAK_CONCRETE 0x40 #define BREAK_2 0x80 +#define BREAK_TYPEMASK BREAK_GLASS|BREAK_METAL|BREAK_FLESH|BREAK_WOOD|BREAK_CONCRETE + /** * Colliding temp entity sounds */ -#define BOUNCE_GLASS BREAK_GLASS -#define BOUNCE_METAL BREAK_METAL -#define BOUNCE_FLESH BREAK_FLESH -#define BOUNCE_WOOD BREAK_WOOD -#define BOUNCE_SHRAP 0x10 -#define BOUNCE_SHELL 0x20 -#define BOUNCE_CONCRETE BREAK_CONCRETE -#define BOUNCE_SHOTSHELL 0x80 +#define BOUNCE_GLASS BREAK_GLASS // "debris/glass%i.wav", Com_RandomLong( 1, 4 ) +#define BOUNCE_METAL BREAK_METAL // "debris/metal%i.wav", Com_RandomLong( 1, 6 ) +#define BOUNCE_FLESH BREAK_FLESH // "debris/flesh%i.wav", Com_RandomLong( 1, 7 ) +#define BOUNCE_WOOD BREAK_WOOD // "debris/wood%i.wav", Com_RandomLong( 1, 4 ) +#define BOUNCE_SHRAP 0x10 // "weapons/ric%i.wav", Com_RandomLong( 1, 5 ) NOTE: unreachable +#define BOUNCE_SHELL 0x20 // "player/pl_shell%i.wav", Com_RandomLong( 1, 3 ) +#define BOUNCE_CONCRETE BREAK_CONCRETE // "debris/concrete%i.wav", Com_RandomLong( 1, 3 ) +#define BOUNCE_SHOTSHELL 0x80 // "weapons/sshell%i.wav", Com_RandomLong( 1, 3 ) /** -* Temp entity bounce sound types +* "Brass" message and TE_MODEL soundtype */ -#define TE_BOUNCE_NULL 0 -#define TE_BOUNCE_SHELL 1 -#define TE_BOUNCE_SHOTSHELL 2 +#define TE_BOUNCE_NULL 0 +#define TE_BOUNCE_SHELL 1 // gun shell, sound is BOUNCE_SHELL +#define TE_BOUNCE_SHOTSHELL 2 // shotgun shell, sound is BOUNCE_SHOTSHELL /** * Spectating camera mode constants diff --git a/reapi/extra/amxmodx/scripting/include/reapi_engine.inc b/reapi/extra/amxmodx/scripting/include/reapi_engine.inc index 1107451a..62f752bd 100644 --- a/reapi/extra/amxmodx/scripting/include/reapi_engine.inc +++ b/reapi/extra/amxmodx/scripting/include/reapi_engine.inc @@ -300,6 +300,24 @@ native bool:rh_is_entity_fullpacked(const host, const entity, const frame = -1); */ native Float:rh_get_realtime(); +/* +* Checks if server paused +* +* @return Returns true if paused, otherwise false. +* +*/ +native bool:rh_is_server_paused(); + +/* +* Set server pause state +* +* @param status pause state +* +* @noreturn +* +*/ +native rh_set_server_pause(const bool:status); + enum MessageHook { INVALID_MESSAGEHOOK = 0 diff --git a/reapi/extra/amxmodx/scripting/include/reapi_gamedll.inc b/reapi/extra/amxmodx/scripting/include/reapi_gamedll.inc index 013eb5ea..9dc9d8c9 100644 --- a/reapi/extra/amxmodx/scripting/include/reapi_gamedll.inc +++ b/reapi/extra/amxmodx/scripting/include/reapi_gamedll.inc @@ -443,7 +443,7 @@ native rg_find_ent_by_class(start_index, const classname[], const bool:useHashTa /* * Finds an entity in the world using Counter-Strike's custom FindEntityByString wrapper, matching by owner. * -* @param start_index Entity index to start searching from. AMX_NULLENT (-1) to start from the first entity +* @param start_index Entity index to start searching from. NULLENT (-1) to start from the first entity * @param classname Classname to search for * * @return true if found, false otherwise @@ -532,7 +532,7 @@ native rg_remove_all_items(const index, const bool:removeSuit = false); * @param index Client index * @param item_name Item classname, if no name, the active item classname * -* @return Entity index of weaponbox, AMX_NULLENT (-1) otherwise +* @return Entity index of weaponbox, NULLENT (-1) otherwise * */ native rg_drop_item(const index, const item_name[]); @@ -718,7 +718,7 @@ native rg_instant_reload_weapons(const index, const weapon = 0); * @param origin The origin of the bomb where it will be planted. * @param angles The angles of the planted bomb. * -* @return Index of bomb entity or AMX_NULLENT (-1) otherwise +* @return Index of bomb entity or NULLENT (-1) otherwise */ native rg_plant_bomb(const index, Float:vecOrigin[3], Float:vecAngles[3] = {0.0,0.0,0.0}); @@ -994,7 +994,7 @@ native bool:rg_get_can_hear_player(const listener, const sender); * * @param index Entity id * -* @return Index of head gib entity or AMX_NULLENT (-1) otherwise +* @return Index of head gib entity or NULLENT (-1) otherwise */ native rg_spawn_head_gib(const index); @@ -1020,7 +1020,7 @@ native rg_spawn_random_gibs(const index, const cGibs, const bool:bHuman = true); * @param iTeam Grenade team, see TEAM_* constants * @param usEvent Event index related to grenade (returned value of precache_event) * -* @return Entity index on success, AMX_NULLENT (-1) otherwise +* @return Entity index on success, NULLENT (-1) otherwise */ native rg_spawn_grenade(WeaponIdType:weaponId, pevOwner, Float:vecSrc[3], Float:vecThrow[3], Float:time, TeamName:iTeam, usEvent = 0); @@ -1028,7 +1028,7 @@ native rg_spawn_grenade(WeaponIdType:weaponId, pevOwner, Float:vecSrc[3], Float: * Spawn a weaponbox entity with its properties * * @param pItem Weapon entity index to attach -* @param pPlayerOwner Player index to remove pItem entity (0 = no weapon owner) +* @param pPlayerOwner Player index to remove pItem entity (NULLENT = no weapon owner) * @param modelName Model name ("models/w_*.mdl") * @param origin Weaponbox origin position * @param angles Weaponbox angles @@ -1036,7 +1036,7 @@ native rg_spawn_grenade(WeaponIdType:weaponId, pevOwner, Float:vecSrc[3], Float: * @param lifeTime Time to stay in world (< 0.0 = use mp_item_staytime cvar value) * @param packAmmo Set if ammo should be removed from weapon owner * -* @return Weaponbox ent index on success, AMX_NULLENT (-1) otherwise +* @return Weaponbox ent index on success, NULLENT (-1) otherwise */ native rg_create_weaponbox(const pItem, const pPlayerOwner, const modelName[], Float:origin[3], Float:angles[3], Float:velocity[3], Float:lifeTime, bool:packAmmo); @@ -1185,6 +1185,18 @@ native rg_disappear(const player); */ native rg_set_observer_mode(const player, const mode); +/* +* Call origin function CBasePlayer::Observer_FindNextPlayer() +* @note Player must be a valid observer (m_afPhysicsFlags & PFLAG_OBSERVER). +* +* @param player Player index. +* @param bReverse If bReverse is true, finding order will be reversed +* @param name Player name to find. +* +* @noreturn +*/ +native rg_observer_find_next_player(const player, const bool:bReverse = false, const name[] = ""); + /* * Emits a death notice (logs, DeathMsg event, win conditions check) * @@ -1221,3 +1233,44 @@ native rg_player_relationship(const player, const target); * @noreturn */ native rg_send_death_message(const pKiller, const pVictim, const pAssister, const pevInflictor, const killerWeaponName[], const DeathMessageFlags:iDeathMessageFlags, const KillRarity:iRarityOfKill); + +/* +* Adds impulse to the player. +* +* @param player Player index. +* @param attacker Attacker index. +* @param flKnockbackForce Knockback force. +* @param flVelModifier Velocity modifier. +* +* @noreturn +*/ +native rg_player_takedamage_impulse(const player, const attacker, const Float:flKnockbackForce, const Float:flVelModifier); + +/* +* Fires a trace line between two origins, retrieving the end point and entity hit. +* +* @param vecStart Start position +* @param vecEnd End position +* @param ignoreMonsters Entity ignore type +* @param ignoreEntity Entity index that trace will ignore, NULLENT if trace should not ignore any entities +* @param ptr Traceresult pointer, use Fakemeta's create_tr2 to instantiate one +* @param traceFlags Additional trace flags, see FTRACE_* constants on cssdk_const.inc +* +* @noreturn +*/ +native rg_trace_line(Float:vecStart[3], Float:vecEnd[3], const ignoreMonsters, const ignoreEntity, const ptr, const traceFlags = 0); + +/* +* Fires a trace hull on a specified origin or between two origins. +* +* @param vecStart Start position +* @param vecEnd End position +* @param ignoreMonsters Entity ignore type +* @param hullNumber Hull type +* @param ignoreEntity Entity index that trace will ignore, NULLENT if trace should not ignore any entities +* @param ptr Traceresult pointer, use Fakemeta's create_tr2 to instantiate one +* @param traceFlags Additional trace flags, see FTRACE_* constants on cssdk_const.inc +* +* @noreturn +*/ +native rg_trace_hull(Float:vecStart[3], Float:vecEnd[3], const ignoreMonsters, const hullNumber, const ignoreEntity, const ptr, const traceFlags = 0); diff --git a/reapi/extra/amxmodx/scripting/include/reapi_gamedll_const.inc b/reapi/extra/amxmodx/scripting/include/reapi_gamedll_const.inc index a0a860c4..03621e61 100644 --- a/reapi/extra/amxmodx/scripting/include/reapi_gamedll_const.inc +++ b/reapi/extra/amxmodx/scripting/include/reapi_gamedll_const.inc @@ -890,14 +890,14 @@ enum GamedllFunc_CBasePlayer /* * Description: Called when a client emits a "pain sound" after received damage. * Return type: void - * Params: (const this) + * Params: (const this, HitBoxGroup:lastHitGroup, bool:hasArmour) */ RG_CBasePlayer_Pain, /* * Description: Called when a client emits a "death sound" after death. * Return type: void - * Params: (const this, lastHitGroup, bool:hasArmour) + * Params: (const this) */ RG_CBasePlayer_DeathSound, @@ -940,6 +940,18 @@ enum GamedllFunc_CBasePlayer * Params: (const this, bool:removeSuit) */ RG_CBasePlayer_RemoveAllItems, + + /* + * Description: - + * Params: (const this) + */ + RG_CBasePlayer_UpdateStatusBar, + + /* + * Description: Called for the victim player after taking damage, when "knockback" and "pain shock" are applied. + * Params: (const this, attacker, Float:flKnockbackForce, Float:flVelModifier) + */ + RG_CBasePlayer_TakeDamageImpulse, }; /** diff --git a/reapi/include/cssdk/common/const.h b/reapi/include/cssdk/common/const.h index 8350e8ae..5437e5b2 100644 --- a/reapi/include/cssdk/common/const.h +++ b/reapi/include/cssdk/common/const.h @@ -667,31 +667,32 @@ #endif // Break Model Defines -#define BREAK_TYPEMASK 0x4F #define BREAK_GLASS 0x01 #define BREAK_METAL 0x02 #define BREAK_FLESH 0x04 #define BREAK_WOOD 0x08 -#define BREAK_SMOKE 0x10 -#define BREAK_TRANS 0x20 +#define BREAK_SMOKE 0x10 // generates black floating particles from shards +#define BREAK_TRANS 0x20 // transparent shard flag (use with any of BREAK_TYPEMASK) #define BREAK_CONCRETE 0x40 #define BREAK_2 0x80 +#define BREAK_TYPEMASK BREAK_GLASS|BREAK_METAL|BREAK_FLESH|BREAK_WOOD|BREAK_CONCRETE + // Colliding temp entity sounds -#define BOUNCE_GLASS BREAK_GLASS -#define BOUNCE_METAL BREAK_METAL -#define BOUNCE_FLESH BREAK_FLESH -#define BOUNCE_WOOD BREAK_WOOD -#define BOUNCE_SHRAP 0x10 -#define BOUNCE_SHELL 0x20 -#define BOUNCE_CONCRETE BREAK_CONCRETE -#define BOUNCE_SHOTSHELL 0x80 - -// Temp entity bounce sound types +#define BOUNCE_GLASS BREAK_GLASS // "debris/glass%i.wav", Com_RandomLong( 1, 4 ) +#define BOUNCE_METAL BREAK_METAL // "debris/metal%i.wav", Com_RandomLong( 1, 6 ) +#define BOUNCE_FLESH BREAK_FLESH // "debris/flesh%i.wav", Com_RandomLong( 1, 7 ) +#define BOUNCE_WOOD BREAK_WOOD // "debris/wood%i.wav", Com_RandomLong( 1, 4 ) +#define BOUNCE_SHRAP 0x10 // "weapons/ric%i.wav", Com_RandomLong( 1, 5 ) NOTE: unreachable +#define BOUNCE_SHELL 0x20 // "player/pl_shell%i.wav", Com_RandomLong( 1, 3 ) +#define BOUNCE_CONCRETE BREAK_CONCRETE // "debris/concrete%i.wav", Com_RandomLong( 1, 3 ) +#define BOUNCE_SHOTSHELL 0x80 // "weapons/sshell%i.wav", Com_RandomLong( 1, 3 ) + +// "Brass" message and TE_MODEL soundtype #define TE_BOUNCE_NULL 0 -#define TE_BOUNCE_SHELL 1 -#define TE_BOUNCE_SHOTSHELL 2 +#define TE_BOUNCE_SHELL 1 // gun shell, sound is BOUNCE_SHELL +#define TE_BOUNCE_SHOTSHELL 2 // shotgun shell, sound is BOUNCE_SHOTSHELL // Rendering constants enum diff --git a/reapi/include/cssdk/dlls/API/CSPlayer.h b/reapi/include/cssdk/dlls/API/CSPlayer.h index 3495ee29..dd97e378 100644 --- a/reapi/include/cssdk/dlls/API/CSPlayer.h +++ b/reapi/include/cssdk/dlls/API/CSPlayer.h @@ -118,6 +118,8 @@ class CCSPlayer: public CCSMonster virtual void Reset() = 0; virtual void OnSpawnEquip(bool addDefault = true, bool equipGame = true) = 0; virtual void SetScoreboardAttributes(CBasePlayer *destination = nullptr) = 0; + virtual void Observer_FindNextPlayer(bool bReverse, const char *name = nullptr) = 0; + virtual void TakeDamageImpulse(CBasePlayer *pAttacker, float flKnockbackForce, float flVelModifier) = 0; CBasePlayer *BasePlayer() const; diff --git a/reapi/include/cssdk/dlls/regamedll_api.h b/reapi/include/cssdk/dlls/regamedll_api.h index c0aa993a..62273fe6 100644 --- a/reapi/include/cssdk/dlls/regamedll_api.h +++ b/reapi/include/cssdk/dlls/regamedll_api.h @@ -40,7 +40,7 @@ #include #define REGAMEDLL_API_VERSION_MAJOR 5 -#define REGAMEDLL_API_VERSION_MINOR 27 +#define REGAMEDLL_API_VERSION_MINOR 30 // CBasePlayer::Spawn hook typedef IHookChainClass IReGameHook_CBasePlayer_Spawn; @@ -630,6 +630,14 @@ typedef IHookChainRegistryClass IReGameHookRegistry_CBa typedef IHookChainClass IReGameHook_CBasePlayer_RemoveAllItems; typedef IHookChainRegistryClass IReGameHookRegistry_CBasePlayer_RemoveAllItems; +// CBasePlayer::UpdateStatusBar hook +typedef IHookChainClass IReGameHook_CBasePlayer_UpdateStatusBar; +typedef IHookChainRegistryClass IReGameHookRegistry_CBasePlayer_UpdateStatusBar; + +// CBasePlayer::TakeDamageImpulse hook +typedef IHookChainClass IReGameHook_CBasePlayer_TakeDamageImpulse; +typedef IHookChainRegistryClass IReGameHookRegistry_CBasePlayer_TakeDamageImpulse; + class IReGameHookchains { public: virtual ~IReGameHookchains() {} @@ -792,6 +800,8 @@ class IReGameHookchains { virtual IReGameHookRegistry_CBasePlayer_PlayerDeathThink *CBasePlayer_PlayerDeathThink() = 0; virtual IReGameHookRegistry_CBasePlayer_Observer_Think *CBasePlayer_Observer_Think() = 0; virtual IReGameHookRegistry_CBasePlayer_RemoveAllItems *CBasePlayer_RemoveAllItems() = 0; + virtual IReGameHookRegistry_CBasePlayer_UpdateStatusBar *CBasePlayer_UpdateStatusBar() = 0; + virtual IReGameHookRegistry_CBasePlayer_TakeDamageImpulse *CBasePlayer_TakeDamageImpulse() = 0; }; struct ReGameFuncs_t { diff --git a/reapi/include/cssdk/engine/rehlds_api.h b/reapi/include/cssdk/engine/rehlds_api.h index 0444b60c..ac415374 100644 --- a/reapi/include/cssdk/engine/rehlds_api.h +++ b/reapi/include/cssdk/engine/rehlds_api.h @@ -38,7 +38,7 @@ #include "pr_dlls.h" #define REHLDS_API_VERSION_MAJOR 3 -#define REHLDS_API_VERSION_MINOR 14 +#define REHLDS_API_VERSION_MINOR 15 //Steam_NotifyClientConnect hook typedef IHookChain IRehldsHook_Steam_NotifyClientConnect; @@ -434,6 +434,9 @@ struct RehldsFuncs_t { void(*MSG_BeginReading)(); double(*GetHostFrameTime)(); struct cmd_function_s *(*GetFirstCmdFunctionHandle)(); + + // Pause + void(*SetServerPause)(bool status); }; class IRehldsApi { diff --git a/reapi/include/cssdk/engine/rehlds_interfaces.h b/reapi/include/cssdk/engine/rehlds_interfaces.h index e2b909fa..392ae9cc 100644 --- a/reapi/include/cssdk/engine/rehlds_interfaces.h +++ b/reapi/include/cssdk/engine/rehlds_interfaces.h @@ -129,4 +129,14 @@ class IRehldsServerData { virtual void SetName(const char* name) = 0; virtual class ISteamGameServer *GetSteamGameServer() = 0; virtual struct netadr_s *GetNetFrom() = 0; + virtual double GetOldTime() = 0; + + virtual void SetNetFrom(struct netadr_s *from) = 0; + virtual void SetWorldmapCrc(uint32 crcValue) = 0; + virtual void SetDecalNameNum(int num) = 0; + + virtual bool IsActive() = 0; + virtual void SetActive(bool state) = 0; + virtual bool IsPaused() = 0; + virtual void SetPaused(bool state) = 0; }; diff --git a/reapi/include/reunion_api.h b/reapi/include/reunion_api.h index 8ba5c363..c8797585 100644 --- a/reapi/include/reunion_api.h +++ b/reapi/include/reunion_api.h @@ -34,6 +34,10 @@ enum reu_authkey_kind class IReunionApi { public: + // NOTE: GetMajorVersion, GetMinorVersion have been since version 0.1.0.92c + int version_major; + int version_minor; + enum { LONG_AUTHID_LEN = 16 diff --git a/reapi/msvc/icon.ico b/reapi/msvc/icon.ico new file mode 100644 index 00000000..8b080d2f Binary files /dev/null and b/reapi/msvc/icon.ico differ diff --git a/reapi/src/hook_callback.cpp b/reapi/src/hook_callback.cpp index fb228ad6..7d03f922 100644 --- a/reapi/src/hook_callback.cpp +++ b/reapi/src/hook_callback.cpp @@ -1319,7 +1319,7 @@ CWeaponBox *CreateWeaponBox(IReGameHook_CreateWeaponBox *chain, CBasePlayerItem return indexOfPDataAmx(chain->callNext(getPrivate(_pItem), getPrivate(_pPlayerOwner), _modelName, vecOriginCopy, vecAnglesCopy, vecVelocityCopy, _lifeTime, _packAmmo)); }; - return getPrivate(callForward(RG_CreateWeaponBox, original, indexOfEdictAmx(pItem->pev), indexOfEdictAmx(pPlayerOwner->pev), modelName, getAmxVector(vecOriginCopy), getAmxVector(vecAnglesCopy), getAmxVector(vecVelocityCopy), lifeTime, packAmmo)); + return getPrivate(callForward(RG_CreateWeaponBox, original, indexOfPDataAmx(pItem), indexOfPDataAmx(pPlayerOwner), modelName, getAmxVector(vecOriginCopy), getAmxVector(vecAnglesCopy), getAmxVector(vecVelocityCopy), lifeTime, packAmmo)); } CGib *SpawnHeadGib(IReGameHook_SpawnHeadGib *chain, entvars_t *pevVictim) @@ -1766,6 +1766,26 @@ void CSGameRules_SendDeathMessage(IReGameHook_CSGameRules_SendDeathMessage *chai callVoidForward(RG_CSGameRules_SendDeathMessage, original, indexOfPDataAmx(pKiller), indexOfEdict(pVictim->pev), indexOfPDataAmx(pAssister), indexOfEdictAmx(pevInflictor), killerWeaponName, iDeathMessageFlags, iRarityOfKill); } +void CBasePlayer_UpdateStatusBar(IReGameHook_CBasePlayer_UpdateStatusBar *chain, CBasePlayer *pthis) +{ + auto original = [chain](int _pthis) + { + chain->callNext(getPrivate(_pthis)); + }; + + callVoidForward(RG_CBasePlayer_UpdateStatusBar, original, indexOfEdict(pthis->pev)); +} + +void CBasePlayer_TakeDamageImpulse(IReGameHook_CBasePlayer_TakeDamageImpulse *chain, CBasePlayer *pthis, CBasePlayer *pAttacker, float flKnockbackForce, float flVelModifier) +{ + auto original = [chain](int _pthis, int _pAttacker, float _flKnockbackForce, float _flVelModifier) + { + chain->callNext(getPrivate(_pthis), getPrivate(_pAttacker), _flKnockbackForce, _flVelModifier); + }; + + callVoidForward(RG_CBasePlayer_TakeDamageImpulse, original, indexOfEdict(pthis->pev), indexOfEdict(pAttacker->pev), flKnockbackForce, flVelModifier); +} + /* * VTC functions */ diff --git a/reapi/src/hook_callback.h b/reapi/src/hook_callback.h index 3e3733a3..1065997a 100644 --- a/reapi/src/hook_callback.h +++ b/reapi/src/hook_callback.h @@ -574,6 +574,8 @@ void CBasePlayer_PlayerDeathThink(IReGameHook_CBasePlayer_PlayerDeathThink *chai void CBasePlayer_Observer_Think(IReGameHook_CBasePlayer_Observer_Think *chain, CBasePlayer *pthis); void CBasePlayer_RemoveAllItems(IReGameHook_CBasePlayer_RemoveAllItems *chain, CBasePlayer *pthis, BOOL removeSuit); void CSGameRules_SendDeathMessage(IReGameHook_CSGameRules_SendDeathMessage *chain, CBaseEntity *pKiller, CBasePlayer *pVictim, CBasePlayer *pAssister, entvars_t *pevInflictor, const char *killerWeaponName, int iDeathMessageFlags, int iRarityOfKill); +void CBasePlayer_UpdateStatusBar(IReGameHook_CBasePlayer_UpdateStatusBar *chain, CBasePlayer *pthis); +void CBasePlayer_TakeDamageImpulse(IReGameHook_CBasePlayer_TakeDamageImpulse *chain, CBasePlayer *pthis, CBasePlayer *pAttacker, float flKnockbackForce, float flVelModifier); /* * VTC functions diff --git a/reapi/src/hook_list.cpp b/reapi/src/hook_list.cpp index df094509..cb8bd17e 100644 --- a/reapi/src/hook_list.cpp +++ b/reapi/src/hook_list.cpp @@ -216,6 +216,8 @@ hook_t hooklist_player[] = { DLL(CBasePlayer_PlayerDeathThink), DLL(CBasePlayer_Observer_Think), DLL(CBasePlayer_RemoveAllItems), + DLL(CBasePlayer_UpdateStatusBar), + DLL(CBasePlayer_TakeDamageImpulse), }; hook_t hooklist_gamerules[] = { diff --git a/reapi/src/hook_list.h b/reapi/src/hook_list.h index 1618afd4..1cdb7bb4 100644 --- a/reapi/src/hook_list.h +++ b/reapi/src/hook_list.h @@ -240,6 +240,8 @@ enum GamedllFunc_CBasePlayer RG_CBasePlayer_PlayerDeathThink, RG_CBasePlayer_Observer_Think, RG_CBasePlayer_RemoveAllItems, + RG_CBasePlayer_UpdateStatusBar, + RG_CBasePlayer_TakeDamageImpulse, // [...] }; diff --git a/reapi/src/mods/mod_reunion_api.cpp b/reapi/src/mods/mod_reunion_api.cpp index 68bed28f..0001666f 100644 --- a/reapi/src/mods/mod_reunion_api.cpp +++ b/reapi/src/mods/mod_reunion_api.cpp @@ -12,28 +12,28 @@ bool ReunionApi_Init() if (!g_ReunionApi) return false; - if (g_ReunionApi->GetMajorVersion() != REUNION_API_VERSION_MAJOR) + if (g_ReunionApi->version_major != REUNION_API_VERSION_MAJOR) { - UTIL_ServerPrint("[%s]: Reunion API major version mismatch; expected %d, real %d\n", Plugin_info.logtag, REUNION_API_VERSION_MAJOR, g_ReunionApi->GetMajorVersion()); + UTIL_ServerPrint("[%s]: Reunion API major version mismatch; expected %d, real %d\n", Plugin_info.logtag, REUNION_API_VERSION_MAJOR, g_ReunionApi->version_major); // need to notify that it is necessary to update the Reunion. - if (g_ReunionApi->GetMajorVersion() < REUNION_API_VERSION_MAJOR) + if (g_ReunionApi->version_major < REUNION_API_VERSION_MAJOR) { UTIL_ServerPrint("[%s]: Please update the Reunion up to a major version API >= %d\n", Plugin_info.logtag, REUNION_API_VERSION_MAJOR); } // need to notify that it is necessary to update the module. - else if (g_ReunionApi->GetMajorVersion() > REUNION_API_VERSION_MAJOR) + else if (g_ReunionApi->version_major > REUNION_API_VERSION_MAJOR) { - UTIL_ServerPrint("[%s]: Please update the %s up to a major version API >= %d\n", Plugin_info.logtag, Plugin_info.logtag, g_ReunionApi->GetMajorVersion()); + UTIL_ServerPrint("[%s]: Please update the %s up to a major version API >= %d\n", Plugin_info.logtag, Plugin_info.logtag, g_ReunionApi->version_major); } return false; } - if (g_ReunionApi->GetMinorVersion() < REUNION_API_VERSION_MINOR) + if (g_ReunionApi->version_minor < REUNION_API_VERSION_MINOR) { - UTIL_ServerPrint("[%s]: Reunion API minor version mismatch; expected at least %d, real %d\n", Plugin_info.logtag, REUNION_API_VERSION_MINOR, g_ReunionApi->GetMinorVersion()); + UTIL_ServerPrint("[%s]: Reunion API minor version mismatch; expected at least %d, real %d\n", Plugin_info.logtag, REUNION_API_VERSION_MINOR, g_ReunionApi->version_minor); UTIL_ServerPrint("[%s]: Please update the Reunion up to a minor version API >= %d\n", Plugin_info.logtag, REUNION_API_VERSION_MINOR); return false; } diff --git a/reapi/src/natives/natives_hookmessage.cpp b/reapi/src/natives/natives_hookmessage.cpp index b56657c1..5f47a375 100644 --- a/reapi/src/natives/natives_hookmessage.cpp +++ b/reapi/src/natives/natives_hookmessage.cpp @@ -188,7 +188,7 @@ cell AMX_NATIVE_CALL SetMessageData(AMX *amx, cell *params) break; case IMessage::ParamType::Angle: case IMessage::ParamType::Coord: - g_activeMessageContext->setParamFloat(number, *(float *)value); + g_activeMessageContext->setParamFloat(number, amx_CellToFloat(*value)); break; case IMessage::ParamType::Byte: case IMessage::ParamType::Char: @@ -266,10 +266,11 @@ cell AMX_NATIVE_CALL GetMessageData(AMX *amx, cell *params) case IMessage::ParamType::Angle: case IMessage::ParamType::Coord: { - float flValue = g_activeMessageContext->getParamFloat(number); + cell value = amx_FloatToCell(g_activeMessageContext->getParamFloat(number)); if (PARAMS_COUNT > 2) - *dstAddr = flValue; - return flValue; + *dstAddr = value; + + return value; } case IMessage::ParamType::Entity: case IMessage::ParamType::Byte: @@ -346,10 +347,10 @@ cell AMX_NATIVE_CALL GetMessageOrigData(AMX *amx, cell *params) case IMessage::ParamType::Angle: case IMessage::ParamType::Coord: { - float flValue = g_activeMessageContext->getOriginalParamFloat(number); + cell value = amx_FloatToCell(g_activeMessageContext->getOriginalParamFloat(number)); if (PARAMS_COUNT > 2) - *dstAddr = flValue; - return flValue; + *dstAddr = value; + return value; } case IMessage::ParamType::Entity: case IMessage::ParamType::Byte: diff --git a/reapi/src/natives/natives_misc.cpp b/reapi/src/natives/natives_misc.cpp index 3f6a3815..4e813bea 100644 --- a/reapi/src/natives/natives_misc.cpp +++ b/reapi/src/natives/natives_misc.cpp @@ -2076,16 +2076,18 @@ cell AMX_NATIVE_CALL rg_send_bartime2(AMX *amx, cell *params) CHECK_CONNECTED(pPlayer, arg_index); CAmxArgs args(amx, params); + int duration = args[arg_time]; float startPercent = args[arg_start_percent]; if (!args[arg_observer]) { EMESSAGE_BEGIN(MSG_ONE_UNRELIABLE, gmsgBarTime2, nullptr, pPlayer->edict()); - EWRITE_SHORT(args[arg_time]); + EWRITE_SHORT(duration); EWRITE_SHORT(startPercent); EMESSAGE_END(); return TRUE; } - pPlayer->CSPlayer()->SetProgressBarTime2(args[arg_time], startPercent); + float timeElapsed = (startPercent / 100.0f) * duration; + pPlayer->CSPlayer()->SetProgressBarTime2(duration, timeElapsed); return TRUE; } @@ -2689,7 +2691,7 @@ cell AMX_NATIVE_CALL rg_spawn_grenade(AMX* amx, cell* params) * Spawn a weaponbox entity with its properties * * @param pItem Weapon entity index to attach -* @param pPlayerOwner Player index to remove pItem entity (0 = no weapon owner) +* @param pPlayerOwner Player index to remove pItem entity (AMX_NULLENT = no weapon owner) * @param modelName Model name ("models/w_*.mdl") * @param origin Weaponbox origin position * @param angles Weaponbox angles @@ -2714,7 +2716,7 @@ cell AMX_NATIVE_CALL rg_create_weaponbox(AMX* amx, cell* params) CBasePlayer *pPlayer = nullptr; - if (params[arg_player] != 0) + if (params[arg_player] > 0) { CHECK_ISPLAYER(arg_player); @@ -3242,6 +3244,34 @@ cell AMX_NATIVE_CALL rg_set_observer_mode(AMX* amx, cell* params) return TRUE; } +/* +* Call origin function CBasePlayer::Observer_FindNextPlayer() +* @note Player must be a valid observer (m_afPhysicsFlags & PFLAG_OBSERVER). +* +* @param player Player index. +* @param bReverse If bReverse is true, finding order will be reversed +* @param name Player name to find. +* +* @noreturn +*/ +cell AMX_NATIVE_CALL rg_observer_find_next_player(AMX* amx, cell* params) +{ + enum args_e { arg_count, arg_index, arg_bReverse, arg_name }; + + CHECK_ISPLAYER(arg_index) + + CBasePlayer *pPlayer = UTIL_PlayerByIndex(params[arg_index]); + CHECK_CONNECTED(pPlayer, arg_index); + + char nameBuf[MAX_PLAYER_NAME_LENGTH]; + const char* name = getAmxString(amx, params[arg_name], nameBuf); + if (strcmp(name, "") == 0) + name = nullptr; + + pPlayer->CSPlayer()->Observer_FindNextPlayer(params[arg_bReverse] != 0, name); + return TRUE; +} + /* * Emits a death notice (logs, DeathMsg event, win conditions check) * @@ -3345,6 +3375,101 @@ cell AMX_NATIVE_CALL rg_send_death_message(AMX *amx, cell *params) return TRUE; } +/* +* Adds impulse to the player. +* +* @param player Player index. +* @param attacker Attacker index. +* @param flKnockbackForce Knockback force. +* @param flVelModifier Velocity modifier. +* +* @noreturn +*/ +cell AMX_NATIVE_CALL rg_player_takedamage_impulse(AMX *amx, cell *params) +{ + enum args_e { arg_count, arg_index, arg_attacker, arg_knockback_force, arg_vel_modifier }; + + CHECK_ISPLAYER(arg_index); + CHECK_ISPLAYER(arg_attacker); + + CBasePlayer *pPlayer = UTIL_PlayerByIndex(params[arg_index]); + CHECK_CONNECTED(pPlayer, arg_index); + + if (!pPlayer->IsAlive()) + { + AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: player %d not alive", __FUNCTION__, params[arg_index]); + return FALSE; + } + + CBasePlayer *pAttacker = UTIL_PlayerByIndex(params[arg_attacker]); + CHECK_CONNECTED(pAttacker, arg_attacker); + + if (!pAttacker->IsAlive()) + { + AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: attacker %d not alive", __FUNCTION__, params[arg_attacker]); + return FALSE; + } + + CAmxArgs args(amx, params); + pPlayer->CSPlayer()->TakeDamageImpulse(pAttacker, args[arg_knockback_force], args[arg_vel_modifier]); + + return TRUE; +} + +/* +* Fires a trace line between two origins, retrieving the end point and entity hit. +* +* @param vecStart Start position +* @param vecEnd End position +* @param ignoreMonsters Entity ignore type +* @param ignoreEntity Entity index that trace will ignore, NULLENT if trace should not ignore any entities +* @param ptr Traceresult pointer, use Fakemeta's create_tr2 to instantiate one +* @param traceFlags Additional trace flags, see FTRACE_* constants on cssdk_const.inc +* +* @noreturn +*/ +cell AMX_NATIVE_CALL rg_trace_line(AMX *amx, cell *params) +{ + enum args_e { arg_count, arg_vec_start, arg_vec_end, arg_ignore_monsters, arg_ignore_entity, arg_trace, arg_trace_flags }; + + edict_t* pEntityIgnore = edictByIndexAmx(params[arg_ignore_entity]); + + CAmxArgs args(amx, params); + + gpGlobals->trace_flags = args[arg_trace_flags]; + g_pengfuncsTable->pfnTraceLine(args[arg_vec_start], args[arg_vec_end], args[arg_ignore_monsters], pEntityIgnore, args[arg_trace]); + + return TRUE; +} + +/* +* Fires a trace hull on a specified origin or between two origins. +* +* @param vecStart Start position +* @param vecEnd End position +* @param ignoreMonsters Entity ignore type +* @param hullNumber Hull type +* @param ignoreEntity Entity index that trace will ignore, NULLENT if trace should not ignore any entities +* @param ptr Traceresult pointer, use Fakemeta's create_tr2 to instantiate one +* @param traceFlags Additional trace flags, see FTRACE_* constants on cssdk_const.inc +* +* @noreturn +*/ +cell AMX_NATIVE_CALL rg_trace_hull(AMX *amx, cell *params) +{ + enum args_e { arg_count, arg_vec_start, arg_vec_end, arg_ignore_monsters, arg_hull_number, arg_ignore_entity, arg_trace, arg_trace_flags }; + + edict_t* pEntityIgnore = edictByIndexAmx(params[arg_ignore_entity]); + + CAmxArgs args(amx, params); + + gpGlobals->trace_flags = args[arg_trace_flags]; + g_pengfuncsTable->pfnTraceHull(args[arg_vec_start], args[arg_vec_end], args[arg_ignore_monsters], args[arg_hull_number], pEntityIgnore, args[arg_trace]); + gpGlobals->trace_flags = 0; + + return TRUE; +} + AMX_NATIVE_INFO Misc_Natives_RG[] = { { "rg_set_animation", rg_set_animation }, @@ -3455,10 +3580,14 @@ AMX_NATIVE_INFO Misc_Natives_RG[] = { "rg_switch_best_weapon", rg_switch_best_weapon }, { "rg_disappear", rg_disappear }, { "rg_set_observer_mode", rg_set_observer_mode }, + { "rg_observer_find_next_player", rg_observer_find_next_player }, { "rg_death_notice", rg_death_notice }, { "rg_player_relationship", rg_player_relationship }, { "rg_send_death_message", rg_send_death_message }, + { "rg_player_takedamage_impulse", rg_player_takedamage_impulse }, + { "rg_trace_line", rg_trace_line }, + { "rg_trace_hull", rg_trace_hull }, { nullptr, nullptr } }; @@ -3730,6 +3859,34 @@ cell AMX_NATIVE_CALL rh_is_entity_fullpacked(AMX *amx, cell *params) return FALSE; } +/* +* Checks if server paused +* +* @return Returns true if paused, otherwise false. +* +* native bool:rh_is_server_paused(); +*/ +cell AMX_NATIVE_CALL rh_is_server_paused(AMX *amx, cell *params) +{ + return g_RehldsData->IsPaused() ? TRUE : FALSE; +} + +/* +* Set server pause state +* +* @param st pause state +* +* @noreturn +* +* native rh_set_server_pause(const bool:status); +*/ +cell AMX_NATIVE_CALL rh_set_server_pause(AMX *amx, cell *params) +{ + enum { arg_count, arg_status }; + g_RehldsFuncs->SetServerPause(params[arg_status] != 0); + return TRUE; +} + AMX_NATIVE_INFO Misc_Natives_RH[] = { { "rh_set_mapname", rh_set_mapname }, @@ -3742,6 +3899,8 @@ AMX_NATIVE_INFO Misc_Natives_RH[] = { "rh_get_realtime", rh_get_realtime }, { "rh_is_entity_fullpacked", rh_is_entity_fullpacked }, { "rh_get_client_connect_time", rh_get_client_connect_time }, + { "rh_is_server_paused", rh_is_server_paused }, + { "rh_set_server_pause", rh_set_server_pause }, { nullptr, nullptr } }; diff --git a/reapi/src/type_conversion.h b/reapi/src/type_conversion.h index 456c9d9a..36e1ccc7 100644 --- a/reapi/src/type_conversion.h +++ b/reapi/src/type_conversion.h @@ -97,6 +97,16 @@ inline size_t indexOfPDataAmx(const T* pdata) return index; } +inline cell amx_FloatToCell(REAL x) +{ + return *(cell *)&x; +} + +inline float amx_CellToFloat(cell x) +{ + return *(REAL *)&x; +} + inline cell getAmxVector(Vector& vec) { return g_amxxapi.PrepareCellArrayA(reinterpret_cast(&vec), 3, true); diff --git a/reapi/version/appversion.bat b/reapi/version/appversion.bat index 0b80dfd8..4702baaf 100644 --- a/reapi/version/appversion.bat +++ b/reapi/version/appversion.bat @@ -23,13 +23,32 @@ set commitURL= set commitCount=0 set branch_name=master -for /f "delims=" %%a in ('wmic OS Get localdatetime ^| find "."') do set "dt=%%a" -set "YYYY=%dt:~0,4%" -set "MM=%dt:~4,2%" -set "DD=%dt:~6,2%" -set "hour=%dt:~8,2%" -set "min=%dt:~10,2%" -set "sec=%dt:~12,2%" +for /f "tokens=*" %%i in ('powershell -NoProfile -Command ^ + "$now = Get-Date; Write-Output ('{0:yyyy}|{0:MM}|{0:dd}|{0:HH}|{0:mm}|{0:ss}' -f $now)"') do ( + for /f "tokens=1-6 delims=|" %%a in ("%%i") do ( + set "YYYY=%%a" + set "MM=%%b" + set "DD=%%c" + set "hour=%%d" + set "min=%%e" + set "sec=%%f" + ) +) + +echo YYYY=%YYYY% +echo MM=%MM% +echo DD=%DD% +echo hour=%hour% +echo min=%min% +echo sec=%sec% + +:: for /f "delims=" %%a in ('wmic OS Get localdatetime ^| find "."') do set "dt=%%a" +:: set "YYYY=%dt:~0,4%" +:: set "MM=%dt:~4,2%" +:: set "DD=%dt:~6,2%" +:: set "hour=%dt:~8,2%" +:: set "min=%dt:~10,2%" +:: set "sec=%dt:~12,2%" :: :: Remove leading zero from MM (e.g 09 > 9) diff --git a/reapi/version/version.h b/reapi/version/version.h index 0f32ed96..d3e8b9db 100644 --- a/reapi/version/version.h +++ b/reapi/version/version.h @@ -6,5 +6,5 @@ #pragma once #define VERSION_MAJOR 5 -#define VERSION_MINOR 26 +#define VERSION_MINOR 29 #define VERSION_MAINTENANCE 0