Merge pull request #298 from Arkshine/feature/gamerules-natives

Introduce get/set_gamerules_*() natives to read/write on the gamerules object
This commit is contained in:
Vincent Herbet 2015-11-03 10:42:35 +01:00
commit eb9405bd97
28 changed files with 3609 additions and 554 deletions

View File

@ -0,0 +1,53 @@
/**
* Do not edit this file. Any changes will be overwritten by the gamedata
* updater or by upgrading your AMX Mod X install.
*
* To override data in this file, create a subdirectory named "custom" and
* place your own gamedata file(s) inside of it. Such files will be parsed
* after AMXX's own.
*
* For more information, see http://wiki.alliedmods.net/Gamedata_Updating_(AMX_Mod_X)
*/
"Games"
{
"#default"
{
"Classes"
{
"CGameRules"
{
"Offsets"
{
"m_bFreezePeriod" // BOOL
{
"type" "integer"
"windows" "4"
"linux" "4"
"mac" "4"
}
"m_bBombDropped" // BOOL
{
"type" "integer"
"windows" "8"
"linux" "8"
"mac" "8"
}
}
}
}
}
}
/**
* Class Hierarchy
* -
* CGameRules
* CHalfLifeMultiplay
* CHalfLifeTraining
* CHalfLifeRules
*/

View File

@ -0,0 +1,710 @@
/**
* Do not edit this file. Any changes will be overwritten by the gamedata
* updater or by upgrading your AMX Mod X install.
*
* To override data in this file, create a subdirectory named "custom" and
* place your own gamedata file(s) inside of it. Such files will be parsed
* after AMXX's own.
*
* For more information, see http://wiki.alliedmods.net/Gamedata_Updating_(AMX_Mod_X)
*/
"Games"
{
"#default"
{
"Classes"
{
"CHalfLifeMultiplay"
{
"Offsets"
{
"m_VoiceGameMgr" // class CVoiceGameMgr
{
"type" "class"
"windows" "16"
"linux" "12"
"mac" "12"
}
"m_fTeamCount" // float
{
"type" "float"
"windows" "48"
"linux" "40"
"mac" "40"
}
"m_flCheckWinConditions" // float
{
"type" "float"
"windows" "52"
"linux" "44"
"mac" "44"
}
"m_fRoundCount" // float
{
"type" "float"
"windows" "56"
"linux" "48"
"mac" "48"
}
"m_iRoundTime" // int
{
"type" "integer"
"windows" "60"
"linux" "52"
"mac" "52"
}
"m_iRoundTimeSecs" // int
{
"type" "integer"
"windows" "64"
"linux" "56"
"mac" "56"
}
"m_iIntroRoundTime" // int
{
"type" "integer"
"windows" "68"
"linux" "60"
"mac" "60"
}
"m_fIntroRoundCount" // float
{
"type" "float"
"windows" "72"
"linux" "64"
"mac" "64"
}
"m_iAccountTerrorist" // int
{
"type" "integer"
"windows" "76"
"linux" "68"
"mac" "68"
}
"m_iAccountCT" // int
{
"type" "integer"
"windows" "80"
"linux" "72"
"mac" "72"
}
"m_iNumTerrorist" // int
{
"type" "integer"
"windows" "84"
"linux" "76"
"mac" "76"
}
"m_iNumCT" // int
{
"type" "integer"
"windows" "88"
"linux" "80"
"mac" "80"
}
"m_iNumSpawnableTerrorist" // int
{
"type" "integer"
"windows" "92"
"linux" "84"
"mac" "84"
}
"m_iNumSpawnableCT" // int
{
"type" "integer"
"windows" "96"
"linux" "88"
"mac" "88"
}
"m_iSpawnPointCount_Terrorist" // int
{
"type" "integer"
"windows" "100"
"linux" "92"
"mac" "92"
}
"m_iSpawnPointCount_CT" // int
{
"type" "integer"
"windows" "104"
"linux" "96"
"mac" "96"
}
"m_iHostagesRescued" // int
{
"type" "integer"
"windows" "108"
"linux" "100"
"mac" "100"
}
"m_iHostagesTouched" // int
{
"type" "integer"
"windows" "112"
"linux" "104"
"mac" "104"
}
"m_iRoundWinStatus" // int
{
"type" "integer"
"windows" "116"
"linux" "108"
"mac" "108"
}
"m_iNumCTWins" // short int
{
"type" "short"
"windows" "120"
"linux" "112"
"mac" "112"
}
"m_iNumTerroristWins" // short int
{
"type" "short"
"windows" "122"
"linux" "114"
"mac" "114"
}
"m_bTargetBombed" // bool
{
"type" "boolean"
"windows" "124"
"linux" "116"
"mac" "116"
}
"m_bBombDefused" // bool
{
"type" "boolean"
"windows" "125"
"linux" "117"
"mac" "117"
}
"m_bMapHasBombTarget" // bool
{
"type" "boolean"
"windows" "126"
"linux" "118"
"mac" "118"
}
"m_bMapHasBombZone" // bool
{
"type" "boolean"
"windows" "127"
"linux" "119"
"mac" "119"
}
"m_bMapHasBuyZone" // bool
{
"type" "boolean"
"windows" "128"
"linux" "120"
"mac" "120"
}
"m_bMapHasRescueZone" // bool
{
"type" "boolean"
"windows" "129"
"linux" "121"
"mac" "121"
}
"m_bMapHasEscapeZone" // bool
{
"type" "boolean"
"windows" "130"
"linux" "122"
"mac" "122"
}
"m_iMapHasVIPSafetyZone" // int
{
"type" "integer"
"windows" "132"
"linux" "124"
"mac" "124"
}
"m_bMapHasCameras" // int
{
"type" "integer"
"windows" "136"
"linux" "128"
"mac" "128"
}
"m_iC4Timer" // int
{
"type" "integer"
"windows" "140"
"linux" "132"
"mac" "132"
}
"m_iC4Guy" // int
{
"type" "integer"
"windows" "144"
"linux" "136"
"mac" "136"
}
"m_iLoserBonus" // int
{
"type" "integer"
"windows" "148"
"linux" "140"
"mac" "140"
}
"m_iNumConsecutiveCTLoses" // int
{
"type" "integer"
"windows" "152"
"linux" "144"
"mac" "144"
}
"m_iNumConsecutiveTerroristLoses" // int
{
"type" "integer"
"windows" "156"
"linux" "148"
"mac" "148"
}
"m_fMaxIdlePeriod" // float
{
"type" "float"
"windows" "160"
"linux" "152"
"mac" "152"
}
"m_iLimitTeams" // int
{
"type" "integer"
"windows" "164"
"linux" "156"
"mac" "156"
}
"m_bLevelInitialized" // bool
{
"type" "boolean"
"windows" "168"
"linux" "160"
"mac" "160"
}
"m_bRoundTerminating" // bool
{
"type" "boolean"
"windows" "169"
"linux" "161"
"mac" "161"
}
"m_bCompleteReset" // bool
{
"type" "boolean"
"windows" "170"
"linux" "162"
"mac" "162"
}
"m_flRequiredEscapeRatio" // float
{
"type" "float"
"windows" "172"
"linux" "164"
"mac" "164"
}
"m_iNumEscapers" // int
{
"type" "integer"
"windows" "176"
"linux" "168"
"mac" "168"
}
"m_iHaveEscaped" // int
{
"type" "integer"
"windows" "180"
"linux" "172"
"mac" "172"
}
"m_bCTCantBuy" // bool
{
"type" "boolean"
"windows" "184"
"linux" "176"
"mac" "176"
}
"m_bTCantBuy" // bool
{
"type" "boolean"
"windows" "185"
"linux" "177"
"mac" "177"
}
"m_flBombRadius" // float
{
"type" "float"
"windows" "188"
"linux" "180"
"mac" "180"
}
"m_iConsecutiveVIP" // int
{
"type" "integer"
"windows" "192"
"linux" "184"
"mac" "184"
}
"m_iTotalGunCount" // int
{
"type" "integer"
"windows" "196"
"linux" "188"
"mac" "188"
}
"m_iTotalGrenadeCount" // int
{
"type" "integer"
"windows" "200"
"linux" "192"
"mac" "192"
}
"m_iTotalArmourCount" // int
{
"type" "integer"
"windows" "204"
"linux" "196"
"mac" "196"
}
"m_iUnBalancedRounds" // int
{
"type" "integer"
"windows" "208"
"linux" "200"
"mac" "200"
}
"m_iNumEscapeRounds" // int
{
"type" "integer"
"windows" "212"
"linux" "204"
"mac" "204"
}
"m_iMapVotes" // int[100]
{
"type" "integer"
"size" "100"
"windows" "216"
"linux" "208"
"mac" "208"
}
"m_iLastPick" // int
{
"type" "integer"
"windows" "616"
"linux" "608"
"mac" "608"
}
"m_iMaxMapTime" // int
{
"type" "integer"
"windows" "620"
"linux" "612"
"mac" "612"
}
"m_iMaxRounds" // int
{
"type" "integer"
"windows" "624"
"linux" "616"
"mac" "616"
}
"m_iTotalRoundsPlayed" // int
{
"type" "integer"
"windows" "628"
"linux" "620"
"mac" "620"
}
"m_iMaxRoundsWon" // int
{
"type" "integer"
"windows" "632"
"linux" "624"
"mac" "624"
}
"m_iStoredSpectValue" // int
{
"type" "integer"
"windows" "636"
"linux" "628"
"mac" "628"
}
"m_flForceCameraValue" // float
{
"type" "float"
"windows" "640"
"linux" "632"
"mac" "632"
}
"m_flForceChaseCamValue" // float
{
"type" "float"
"windows" "644"
"linux" "636"
"mac" "636"
}
"m_flFadeToBlackValue" // float
{
"type" "float"
"windows" "648"
"linux" "640"
"mac" "640"
}
"m_pVIP" // CBasePlayer*
{
"type" "classptr"
"windows" "652"
"linux" "644"
"mac" "644"
}
"VIPQueue" // CBasePlayer*[5]
{
"type" "classptr"
"size" "5"
"windows" "656"
"linux" "648"
"mac" "648"
}
"m_flIntermissionEndTime" // float
{
"type" "float"
"windows" "676"
"linux" "668"
"mac" "668"
}
"m_flIntermissionStartTime" // float
{
"type" "float"
"windows" "680"
"linux" "672"
"mac" "672"
}
"m_iEndIntermissionButtonHit" // BOOL
{
"type" "integer"
"windows" "684"
"linux" "676"
"mac" "676"
}
"m_tmNextPeriodicThink" // float
{
"type" "float"
"windows" "688"
"linux" "680"
"mac" "680"
}
"m_bFirstConnected" // bool
{
"type" "boolean"
"windows" "692"
"linux" "684"
"mac" "684"
}
"m_bInCareerGame" // bool
{
"type" "boolean"
"windows" "693"
"linux" "685"
"mac" "685"
}
"m_fCareerRoundMenuTime" // float
{
"type" "float"
"windows" "696"
"linux" "688"
"mac" "688"
}
"m_iCareerMatchWins" // int
{
"type" "integer"
"windows" "700"
"linux" "692"
"mac" "692"
}
"m_iRoundWinDifference" // int
{
"type" "integer"
"windows" "704"
"linux" "696"
"mac" "696"
}
"m_fCareerMatchMenuTime" // float
{
"type" "float"
"windows" "708"
"linux" "700"
"mac" "700"
}
"m_bSkipSpawn" // bool
{
"type" "boolean"
"windows" "712"
"linux" "704"
"mac" "704"
}
}
}
}
}
}
/**
* Class Hierarchy
* -
* CGameRules
* CHalfLifeMultiplay
*/

View File

@ -0,0 +1,79 @@
/**
* Do not edit this file. Any changes will be overwritten by the gamedata
* updater or by upgrading your AMX Mod X install.
*
* To override data in this file, create a subdirectory named "custom" and
* place your own gamedata file(s) inside of it. Such files will be parsed
* after AMXX's own.
*
* For more information, see http://wiki.alliedmods.net/Gamedata_Updating_(AMX_Mod_X)
*/
"Games"
{
"#default"
{
"Classes"
{
"CHalfLifeTraining"
{
"Offsets"
{
"FillAccountTime" // float
{
"type" "float"
"windows" "708"
"linux" "708"
"mac" "708"
}
"ServerRestartTime" // float
{
"type" "float"
"windows" "712"
"linux" "712"
"mac" "712"
}
"fInBuyArea" // BOOL
{
"type" "integer"
"windows" "716"
"linux" "716"
"mac" "716"
}
"fVisitedBuyArea" // BOOL
{
"type" "integer"
"windows" "720"
"linux" "720"
"mac" "720"
}
"fVGUIMenus" // bool
{
"type" "boolean"
"windows" "724"
"linux" "724"
"mac" "724"
}
}
}
}
}
}
/**
* Class Hierarchy
* -
* CGameRules
* CHalfLifeMultiplay
* CHalfLifeTraining
*/

View File

@ -0,0 +1,660 @@
/**
* Do not edit this file. Any changes will be overwritten by the gamedata
* updater or by upgrading your AMX Mod X install.
*
* To override data in this file, create a subdirectory named "custom" and
* place your own gamedata file(s) inside of it. Such files will be parsed
* after AMXX's own.
*
* For more information, see http://wiki.alliedmods.net/Gamedata_Updating_(AMX_Mod_X)
*/
"Games"
{
"#default"
{
"Classes"
{
"CDoDTeamPlay"
{
"Offsets"
{
"m_RoundDoesCount" // int
{
"type" "integer"
"windows" "4"
"linux" "4"
"mac" "4"
}
"m_DoDCameraState" // int
{
"type" "integer"
"windows" "8"
"linux" "8"
"mac" "8"
}
"m_RoundParaCanJoin" // int
{
"type" "integer"
"windows" "12"
"linux" "12"
"mac" "12"
}
"m_flGoodToGoTime" // float
{
"type" "float"
"windows" "16"
"linux" "16"
"mac" "16"
}
"m_flRoundTime" // float
{
"type" "float"
"windows" "20"
"linux" "20"
"mac" "20"
}
"m_flCanJoinTime" // float
{
"type" "float"
"windows" "24"
"linux" "24"
"mac" "24"
}
"m_flRestartTime" // float
{
"type" "float"
"windows" "28"
"linux" "28"
"mac" "28"
}
"m_flFinalCheckTime" // float
{
"type" "float"
"windows" "32"
"linux" "32"
"mac" "32"
}
"m_flDoDMapTime" // float
{
"type" "float"
"windows" "36"
"linux" "36"
"mac" "36"
}
"m_flAlliesWaveTime" // float
{
"type" "float"
"windows" "40"
"linux" "40"
"mac" "40"
}
"m_flAxisWaveTime" // float
{
"type" "float"
"windows" "44"
"linux" "44"
"mac" "44"
}
"m_flAlliesRespawn" // float
{
"type" "float"
"windows" "48"
"linux" "48"
"mac" "48"
}
"m_flAxisRespawn" // float
{
"type" "float"
"windows" "52"
"linux" "52"
"mac" "52"
}
"m_iTeamScores" // int[32]
{
"type" "integer"
"size" "32"
"windows" "56"
"linux" "56"
"mac" "56"
}
"m_szTeamNames" // char*[32]
{
"type" "stringptr"
"size" "32"
"windows" "184"
"linux" "184"
"mac" "184"
}
"m_flSpamResetTime" // float
{
"type" "float"
"windows" "312"
"linux" "312"
"mac" "312"
}
"m_bClanMatch" // bool
{
"type" "boolean"
"windows" "316"
"linux" "316"
"mac" "316"
}
"m_bClanMatchActive" // bool
{
"type" "boolean"
"windows" "317"
"linux" "317"
"mac" "317"
}
"m_szAuthID" // char[32]
{
"type" "string"
"size" "32"
"windows" "318"
"linux" "318"
"mac" "318"
}
"m_vKickENT" // CBasePlayer*
{
"type" "classptr"
"windows" "352"
"linux" "352"
"mac" "352"
}
"m_vKick" // int
{
"type" "integer"
"windows" "356"
"linux" "356"
"mac" "356"
}
"m_vKickVotes" // int
{
"type" "integer"
"windows" "360"
"linux" "360"
"mac" "360"
}
"m_vKickSessionState" // int
{
"type" "integer"
"windows" "364"
"linux" "364"
"mac" "364"
}
"m_vKickTime" // float
{
"type" "float"
"windows" "368"
"linux" "368"
"mac" "368"
}
"m_rRoundStartCount" // float
{
"type" "float"
"windows" "372"
"linux" "372"
"mac" "372"
}
"m_rReadyToUnFreeze" // int
{
"type" "integer"
"windows" "376"
"linux" "376"
"mac" "376"
}
"gr_gameRules" // int
{
"type" "integer"
"windows" "380"
"linux" "380"
"mac" "380"
}
"m_GamePlayRules" // gameplay_rules_t
{
"type" "structure"
"windows" "384"
"linux" "384"
"mac" "384"
}
"m_iNumAlliesAlive" // int
{
"type" "integer"
"windows" "432"
"linux" "432"
"mac" "432"
}
"m_iNumAxisAlive" // int
{
"type" "integer"
"windows" "436"
"linux" "436"
"mac" "436"
}
"m_iNumAlliesOnTeam" // int
{
"type" "integer"
"windows" "440"
"linux" "440"
"mac" "440"
}
"m_iNumAxisOnTeam" // int
{
"type" "integer"
"windows" "444"
"linux" "444"
"mac" "444"
}
"m_Camera" // short unsigned int
{
"type" "short"
"unsigned" "1"
"windows" "448"
"linux" "448"
"mac" "448"
}
"m_usVoice" // short unsigned int
{
"type" "short"
"unsigned" "1"
"windows" "450"
"linux" "450"
"mac" "450"
}
"m_bodyDamage" // short unsigned int
{
"type" "short"
"unsigned" "1"
"windows" "452"
"linux" "452"
"mac" "452"
}
"m_roundRestartSound" // short unsigned int
{
"type" "short"
"unsigned" "1"
"windows" "454"
"linux" "454"
"mac" "454"
}
"m_gerVoice" // short unsigned int
{
"type" "short"
"unsigned" "1"
"windows" "456"
"linux" "456"
"mac" "456"
}
"m_Pain" // short unsigned int
{
"type" "short"
"unsigned" "1"
"windows" "458"
"linux" "458"
"mac" "458"
}
"m_Smoke" // short unsigned int
{
"type" "short"
"unsigned" "1"
"windows" "460"
"linux" "460"
"mac" "460"
}
"m_Prone" // short unsigned int
{
"type" "short"
"unsigned" "1"
"windows" "462"
"linux" "462"
"mac" "462"
}
"m_BloodSprite" // short unsigned int
{
"type" "short"
"unsigned" "1"
"windows" "464"
"linux" "464"
"mac" "464"
}
"m_BloodStream" // short unsigned int
{
"type" "short"
"unsigned" "1"
"windows" "466"
"linux" "466"
"mac" "466"
}
"m_BulletTracers" // short unsigned int
{
"type" "short"
"unsigned" "1"
"windows" "468"
"linux" "468"
"mac" "468"
}
"m_SparkShower" // short unsigned int
{
"type" "short"
"unsigned" "1"
"windows" "470"
"linux" "470"
"mac" "470"
}
"m_ScreenFades" // short unsigned int
{
"type" "short"
"unsigned" "1"
"windows" "472"
"linux" "472"
"mac" "472"
}
"m_BubbleTrails" // short unsigned int
{
"type" "short"
"unsigned" "1"
"windows" "474"
"linux" "474"
"mac" "474"
}
"m_Bubbles" // short unsigned int
{
"type" "short"
"unsigned" "1"
"windows" "476"
"linux" "476"
"mac" "476"
}
"m_Shards" // short unsigned int
{
"type" "short"
"unsigned" "1"
"windows" "478"
"linux" "478"
"mac" "478"
}
"m_Explosion" // short unsigned int
{
"type" "short"
"unsigned" "1"
"windows" "480"
"linux" "480"
"mac" "480"
}
"m_PopHelmet" // short unsigned int
{
"type" "short"
"unsigned" "1"
"windows" "482"
"linux" "482"
"mac" "482"
}
"m_RoundReset" // short unsigned int
{
"type" "short"
"unsigned" "1"
"windows" "484"
"linux" "484"
"mac" "484"
}
"m_RocketTrail" // short unsigned int
{
"type" "short"
"unsigned" "1"
"windows" "486"
"linux" "486"
"mac" "486"
}
"sNextMap" // char[32]
{
"type" "string"
"size" "32"
"windows" "488"
"linux" "488"
"mac" "488"
}
"MapChangeFromTime" // int
{
"type" "integer"
"windows" "520"
"linux" "520"
"mac" "520"
}
"m_bIsRoundFrozen" // bool
{
"type" "boolean"
"windows" "524"
"linux" "524"
"mac" "524"
}
"m_DisableDeathMessages" // BOOL
{
"type" "integer"
"windows" "528"
"linux" "528"
"mac" "528"
}
"m_DisableDeathPenalty" // BOOL
{
"type" "integer"
"windows" "532"
"linux" "532"
"mac" "532"
}
"m_pParaTimer" // CDodParaRoundTimer*
{
"type" "classptr"
"windows" "536"
"linux" "536"
"mac" "536"
}
"m_RoundState" // int
{
"type" "integer"
"windows" "540"
"linux" "540"
"mac" "540"
}
"m_bRoundRestarting" // BOOL
{
"type" "integer"
"windows" "544"
"linux" "544"
"mac" "544"
}
"m_bAwaitingReadyRestart" // BOOL
{
"type" "integer"
"windows" "548"
"linux" "548"
"mac" "548"
}
"m_bHeardAlliesReady" // BOOL
{
"type" "integer"
"windows" "552"
"linux" "552"
"mac" "552"
}
"m_bHeardAxisReady" // BOOL
{
"type" "integer"
"windows" "556"
"linux" "556"
"mac" "556"
}
"m_flRestartRoundTime" // float
{
"type" "float"
"windows" "560"
"linux" "560"
"mac" "560"
}
"m_fLogScoresTime" // float
{
"type" "float"
"windows" "564"
"linux" "564"
"mac" "564"
}
"m_flIntermissionEndTime" // float
{
"type" "float"
"windows" "568"
"linux" "568"
"mac" "568"
}
"m_iEndIntermissionButtonHit" // BOOL
{
"type" "integer"
"windows" "572"
"linux" "572"
"mac" "572"
}
}
}
}
}
}
/**
* Class Hierarchy
* -
* CGameRules
* CDoDTeamPlay
*/

View File

@ -0,0 +1,243 @@
/**
* Do not edit this file. Any changes will be overwritten by the gamedata
* updater or by upgrading your AMX Mod X install.
*
* To override data in this file, create a subdirectory named "custom" and
* place your own gamedata file(s) inside of it. Such files will be parsed
* after AMXX's own.
*
* For more information, see http://wiki.alliedmods.net/Gamedata_Updating_(AMX_Mod_X)
*/
"Games"
{
"#default"
{
"Classes"
{
"CSPDoDRules"
{
"Offsets"
{
"m_Camera" // short unsigned int
{
"type" "short"
"unsigned" "1"
"windows" "4"
"linux" "4"
"mac" "4"
}
"m_usVoice" // short unsigned int
{
"type" "short"
"unsigned" "1"
"windows" "6"
"linux" "6"
"mac" "6"
}
"m_bodyDamage" // short unsigned int
{
"type" "short"
"unsigned" "1"
"windows" "8"
"linux" "8"
"mac" "8"
}
"m_roundRestartSound" // short unsigned int
{
"type" "short"
"unsigned" "1"
"windows" "10"
"linux" "10"
"mac" "10"
}
"m_gerVoice" // short unsigned int
{
"type" "short"
"unsigned" "1"
"windows" "12"
"linux" "12"
"mac" "12"
}
"m_Pain" // short unsigned int
{
"type" "short"
"unsigned" "1"
"windows" "14"
"linux" "14"
"mac" "14"
}
"m_Smoke" // short unsigned int
{
"type" "short"
"unsigned" "1"
"windows" "16"
"linux" "16"
"mac" "16"
}
"m_BloodSprite" // short unsigned int
{
"type" "short"
"unsigned" "1"
"windows" "18"
"linux" "18"
"mac" "18"
}
"m_Prone" // short unsigned int
{
"type" "short"
"unsigned" "1"
"windows" "20"
"linux" "20"
"mac" "20"
}
"m_BloodStream" // short unsigned int
{
"type" "short"
"unsigned" "1"
"windows" "22"
"linux" "22"
"mac" "22"
}
"m_BulletTracers" // short unsigned int
{
"type" "short"
"unsigned" "1"
"windows" "24"
"linux" "24"
"mac" "24"
}
"m_SparkShower" // short unsigned int
{
"type" "short"
"unsigned" "1"
"windows" "26"
"linux" "26"
"mac" "26"
}
"m_ScreenFades" // short unsigned int
{
"type" "short"
"unsigned" "1"
"windows" "28"
"linux" "28"
"mac" "28"
}
"m_BubbleTrails" // short unsigned int
{
"type" "short"
"unsigned" "1"
"windows" "30"
"linux" "30"
"mac" "30"
}
"m_Bubbles" // short unsigned int
{
"type" "short"
"unsigned" "1"
"windows" "32"
"linux" "32"
"mac" "32"
}
"m_Shards" // short unsigned int
{
"type" "short"
"unsigned" "1"
"windows" "34"
"linux" "34"
"mac" "34"
}
"m_Explosion" // short unsigned int
{
"type" "short"
"unsigned" "1"
"windows" "36"
"linux" "36"
"mac" "36"
}
"m_DeadBodies" // short unsigned int
{
"type" "short"
"unsigned" "1"
"windows" "38"
"linux" "38"
"mac" "38"
}
"m_PopHelmet" // short unsigned int
{
"type" "short"
"unsigned" "1"
"windows" "40"
"linux" "40"
"mac" "40"
}
"m_RoundReset" // short unsigned int
{
"type" "short"
"unsigned" "1"
"windows" "42"
"linux" "42"
"mac" "42"
}
"m_RocketTrail" // short unsigned int
{
"type" "short"
"unsigned" "1"
"windows" "44"
"linux" "44"
"mac" "44"
}
}
}
}
}
}
/**
* Class Hierarchy
* -
* CGameRules
* CSPDoDRules
*/

View File

@ -0,0 +1,52 @@
/**
* Do not edit this file. Any changes will be overwritten by the gamedata
* updater or by upgrading your AMX Mod X install.
*
* To override data in this file, create a subdirectory named "custom" and
* place your own gamedata file(s) inside of it. Such files will be parsed
* after AMXX's own.
*
* For more information, see http://wiki.alliedmods.net/Gamedata_Updating_(AMX_Mod_X)
*/
"Games"
{
"#default"
{
"Classes"
{
"CHalfLifeCoopplay"
{
"Offsets"
{
"m_DisableDeathMessages" // BOOL
{
"type" "integer"
"windows" "12"
"linux" "12"
"mac" "12"
}
"m_DisableDeathPenalty" // BOOL
{
"type" "integer"
"windows" "16"
"linux" "16"
"mac" "16"
}
}
}
}
}
}
/**
* Class Hierarchy
* -
* CGameRules
* CHalfLifeMultiplay
* CHalfLifeCoopplay
*/

View File

@ -0,0 +1,88 @@
/**
* Do not edit this file. Any changes will be overwritten by the gamedata
* updater or by upgrading your AMX Mod X install.
*
* To override data in this file, create a subdirectory named "custom" and
* place your own gamedata file(s) inside of it. Such files will be parsed
* after AMXX's own.
*
* For more information, see http://wiki.alliedmods.net/Gamedata_Updating_(AMX_Mod_X)
*/
"Games"
{
"#default"
{
"Classes"
{
"CHalfLifeCTFplay"
{
"Offsets"
{
"m_DisableDeathMessages" // BOOL
{
"type" "integer"
"windows" "12"
"linux" "12"
"mac" "12"
}
"m_DisableDeathPenalty" // BOOL
{
"type" "integer"
"windows" "16"
"linux" "16"
"mac" "16"
}
"m_fRefreshScores" // BOOL
{
"type" "integer"
"windows" "20"
"linux" "20"
"mac" "20"
}
"m_flNextStatsSend" // float
{
"type" "float"
"windows" "24"
"linux" "24"
"mac" "24"
}
"m_iStatsPhase" // int
{
"type" "integer"
"windows" "28"
"linux" "28"
"mac" "28"
}
"m_iStatsPlayer" // int
{
"type" "integer"
"windows" "32"
"linux" "32"
"mac" "32"
}
}
}
}
}
}
/**
* Class Hierarchy
* -
* CGameRules
* CHalfLifeMultiplay
* CHalfLifeCTFplay
*/

View File

@ -0,0 +1,51 @@
/**
* Do not edit this file. Any changes will be overwritten by the gamedata
* updater or by upgrading your AMX Mod X install.
*
* To override data in this file, create a subdirectory named "custom" and
* place your own gamedata file(s) inside of it. Such files will be parsed
* after AMXX's own.
*
* For more information, see http://wiki.alliedmods.net/Gamedata_Updating_(AMX_Mod_X)
*/
"Games"
{
"#default"
{
"Classes"
{
"CHalfLifeMultiplay"
{
"Offsets"
{
"m_flIntermissionEndTime" // float
{
"type" "float"
"windows" "4"
"linux" "4"
"mac" "4"
}
"m_iEndIntermissionButtonHit" // BOOL
{
"type" "integer"
"windows" "8"
"linux" "8"
"mac" "8"
}
}
}
}
}
}
/**
* Class Hierarchy
* -
* CGameRules
* CHalfLifeMultiplay
*/

View File

@ -0,0 +1,71 @@
/**
* Do not edit this file. Any changes will be overwritten by the gamedata
* updater or by upgrading your AMX Mod X install.
*
* To override data in this file, create a subdirectory named "custom" and
* place your own gamedata file(s) inside of it. Such files will be parsed
* after AMXX's own.
*
* For more information, see http://wiki.alliedmods.net/Gamedata_Updating_(AMX_Mod_X)
*/
"Games"
{
"#default"
{
"Classes"
{
"CHalfLifeTeamplay"
{
"Offsets"
{
"m_DisableDeathMessages" // BOOL
{
"type" "integer"
"windows" "12"
"linux" "12"
"mac" "12"
}
"m_DisableDeathPenalty" // BOOL
{
"type" "integer"
"windows" "16"
"linux" "16"
"mac" "16"
}
"m_teamLimit" // BOOL
{
"type" "integer"
"windows" "20"
"linux" "20"
"mac" "20"
}
"m_szTeamList" // char[512]
{
"type" "string"
"size" "512"
"windows" "24"
"linux" "24"
"mac" "24"
}
}
}
}
}
}
/**
* Class Hierarchy
* -
* CGameRules
* CHalfLifeMultiplay
* CHalfLifeTeamplay
*/

View File

@ -0,0 +1,90 @@
/**
* Do not edit this file. Any changes will be overwritten by the gamedata
* updater or by upgrading your AMX Mod X install.
*
* To override data in this file, create a subdirectory named "custom" and
* place your own gamedata file(s) inside of it. Such files will be parsed
* after AMXX's own.
*
* For more information, see http://wiki.alliedmods.net/Gamedata_Updating_(AMX_Mod_X)
*/
"Game Master"
{
"cstrike/offsets-cgamerules.txt"
{
"game" "cstrike"
"game" "czero"
}
"cstrike/offsets-chalflifemultiplay.txt"
{
"game" "cstrike"
"game" "czero"
}
"cstrike/offsets-chalflifetraining.txt"
{
"game" "cstrike"
"game" "czero"
}
"dod/offsets-cdodteamplay.txt"
{
"game" "dod"
}
"dod/offsets-cspdodrules.txt"
{
"game" "dod"
}
"gearbox/offsets-chalflifemultiplay.txt"
{
"game" "gearbox"
}
"gearbox/offsets-chalflifectfplay.txt"
{
"game" "gearbox"
}
"gearbox/offsets-chalflifecoopplay.txt"
{
"game" "gearbox"
}
"gearbox/offsets-chalflifeteamplay.txt"
{
"game" "gearbox"
}
"tfc/offsets-chalflifemultiplay.txt"
{
"game" "tfc"
}
"tfc/offsets-chalflifeteamplay.txt"
{
"game" "tfc"
}
"tfc/offsets-cteamfortress.txt"
{
"game" "tfc"
}
"valve/offsets-chalflifemultiplay.txt"
{
"game" "valve"
}
"valve/offsets-chalflifeteamplay.txt"
{
"game" "valve"
}
}

View File

@ -0,0 +1,60 @@
/**
* Do not edit this file. Any changes will be overwritten by the gamedata
* updater or by upgrading your AMX Mod X install.
*
* To override data in this file, create a subdirectory named "custom" and
* place your own gamedata file(s) inside of it. Such files will be parsed
* after AMXX's own.
*
* For more information, see http://wiki.alliedmods.net/Gamedata_Updating_(AMX_Mod_X)
*/
"Games"
{
"#default"
{
"Classes"
{
"CHalfLifeMultiplay"
{
"Offsets"
{
"m_flIntermissionEndTime" // float
{
"type" "float"
"windows" "4"
"linux" "4"
"mac" "4"
}
"m_flIntermissionStartTime" // float
{
"type" "float"
"windows" "8"
"linux" "8"
"mac" "8"
}
"m_iEndIntermissionButtonHit" // BOOL
{
"type" "integer"
"windows" "12"
"linux" "12"
"mac" "12"
}
}
}
}
}
}
/**
* Class Hierarchy
* -
* CGameRules
* CHalfLifeMultiplay
*/

View File

@ -0,0 +1,52 @@
/**
* Do not edit this file. Any changes will be overwritten by the gamedata
* updater or by upgrading your AMX Mod X install.
*
* To override data in this file, create a subdirectory named "custom" and
* place your own gamedata file(s) inside of it. Such files will be parsed
* after AMXX's own.
*
* For more information, see http://wiki.alliedmods.net/Gamedata_Updating_(AMX_Mod_X)
*/
"Games"
{
"#default"
{
"Classes"
{
"CHalfLifeTeamplay"
{
"Offsets"
{
"m_DisableDeathMessages" // BOOL
{
"type" "integer"
"windows" "16"
"linux" "16"
"mac" "16"
}
"m_DisableDeathPenalty" // BOOL
{
"type" "integer"
"windows" "20"
"linux" "20"
"mac" "20"
}
}
}
}
}
}
/**
* Class Hierarchy
* -
* CGameRules
* CHalfLifeMultiplay
* CHalfLifeTeamplay
*/

View File

@ -0,0 +1,44 @@
/**
* Do not edit this file. Any changes will be overwritten by the gamedata
* updater or by upgrading your AMX Mod X install.
*
* To override data in this file, create a subdirectory named "custom" and
* place your own gamedata file(s) inside of it. Such files will be parsed
* after AMXX's own.
*
* For more information, see http://wiki.alliedmods.net/Gamedata_Updating_(AMX_Mod_X)
*/
"Games"
{
"#default"
{
"Classes"
{
"CTeamFortress"
{
"Offsets"
{
"m_VoiceGameMgr" // class CVoiceGameMgr
{
"type" "class"
"windows" "28"
"linux" "24"
"mac" "24"
}
}
}
}
}
}
/**
* Class Hierarchy
* -
* CGameRules
* CHalfLifeMultiplay
* CHalfLifeTeamplay
* CTeamFortress
*/

View File

@ -0,0 +1,51 @@
/**
* Do not edit this file. Any changes will be overwritten by the gamedata
* updater or by upgrading your AMX Mod X install.
*
* To override data in this file, create a subdirectory named "custom" and
* place your own gamedata file(s) inside of it. Such files will be parsed
* after AMXX's own.
*
* For more information, see http://wiki.alliedmods.net/Gamedata_Updating_(AMX_Mod_X)
*/
"Games"
{
"#default"
{
"Classes"
{
"CHalfLifeMultiplay"
{
"Offsets"
{
"m_flIntermissionEndTime" // float
{
"type" "float"
"windows" "4"
"linux" "4"
"mac" "4"
}
"m_iEndIntermissionButtonHit" // BOOL
{
"type" "integer"
"windows" "8"
"linux" "8"
"mac" "8"
}
}
}
}
}
}
/**
* Class Hierarchy
* -
* CGameRules
* CHalfLifeMultiplay
*/

View File

@ -0,0 +1,71 @@
/**
* Do not edit this file. Any changes will be overwritten by the gamedata
* updater or by upgrading your AMX Mod X install.
*
* To override data in this file, create a subdirectory named "custom" and
* place your own gamedata file(s) inside of it. Such files will be parsed
* after AMXX's own.
*
* For more information, see http://wiki.alliedmods.net/Gamedata_Updating_(AMX_Mod_X)
*/
"Games"
{
"#default"
{
"Classes"
{
"CHalfLifeTeamplay"
{
"Offsets"
{
"m_DisableDeathMessages" // BOOL
{
"type" "integer"
"windows" "12"
"linux" "12"
"mac" "12"
}
"m_DisableDeathPenalty" // BOOL
{
"type" "integer"
"windows" "16"
"linux" "16"
"mac" "16"
}
"m_teamLimit" // BOOL
{
"type" "integer"
"windows" "20"
"linux" "20"
"mac" "20"
}
"m_szTeamList" // char[512]
{
"type" "string"
"size" "512"
"windows" "24"
"linux" "24"
"mac" "24"
}
}
}
}
}
}
/**
* Class Hierarchy
* -
* CGameRules
* CHalfLifeMultiplay
* CHalfLifeTeamplay
*/

View File

@ -40,6 +40,18 @@
"read" "2"
}
}
"g_pGameRules"
{
"signature" "g_pGameRules"
"windows"
{
"read" "2"
}
"read" "0"
}
}
"Signatures"
@ -66,6 +78,14 @@
"linux" "@realtime"
"mac" "@realtime"
}
"g_pGameRules" // CGameRules *g_pGameRules
{
"library" "server"
"windows" "\x8B\x2A\x2A\x2A\x2A\x2A\x85\x2A\x74\x2A\x8B\x2A\xFF\x2A\x2A\xA1" // StartFrame()
"linux" "@g_pGameRules"
"mac" "@g_pGameRules"
}
}
}
}

View File

@ -14,7 +14,8 @@ binary.sources = [
'engfunc.cpp',
'fakemeta_amxx.cpp',
'pdata.cpp',
'pdata_gc.cpp',
'pdata_entities.cpp',
'pdata_gamerules.cpp',
'forward.cpp',
'fm_tr.cpp',
'pev.cpp',

View File

@ -15,9 +15,12 @@
#include "sh_stack.h"
IGameConfig *CommonConfig;
IGameConfig *GamerulesConfig;
IGameConfigManager *ConfigManager;
HLTypeConversion TypeConversion;
void *GameRulesReferenceAddress;
void *GameRulesAddress;
void OnAmxxAttach()
{
@ -39,17 +42,30 @@ void OnAmxxAttach()
ConfigManager = MF_GetConfigManager();
char error[256];
error[0] = '\0';
char error[256] = "";
if (!ConfigManager->LoadGameConfigFile("common.games", &CommonConfig, error, sizeof(error)) && error[0] != '\0')
{
MF_Log("Could not read common.games gamedata: %s", error);
MF_Log("get/set/find_ent_data* natives have been disabled");
MF_Log("get/set_ent_data* natives have been disabled because common.games gamedata could not be read: %s", error);
return;
}
MF_AddNatives(pdata_gc_natives);
*error = '\0';
if (!ConfigManager->LoadGameConfigFile("common.games/gamerules.games", &GamerulesConfig, error, sizeof(error)) && error[0] != '\0')
{
MF_Log("get/set_gamerules_* natives have been disabled because common.games/gamerules.games gamedata could not be read: %s", error);
return;
}
if (!CommonConfig->GetAddress("g_pGameRules", &GameRulesReferenceAddress) || !GameRulesReferenceAddress)
{
MF_Log("get/set_gamerules_* natives have been disabled because g_pGameRules address could not be found. ");
return;
}
MF_AddNatives(pdata_entities_natives);
MF_AddNatives(pdata_gamerules_natives);
}
void OnPluginsLoaded()
@ -63,6 +79,9 @@ extern ke::Vector<KVD_Wrapper *> g_FreeKVDWs;
void OnAmxxDetach()
{
ConfigManager->CloseGameConfigFile(CommonConfig);
ConfigManager->CloseGameConfigFile(GamerulesConfig);
while (!g_FreeTRs.empty())
{
delete g_FreeTRs.front();
@ -78,6 +97,11 @@ void OnAmxxDetach()
void ServerActivate(edict_t *pEdictList, int edictCount, int clientMax)
{
if (GameRulesReferenceAddress)
{
GameRulesAddress = **reinterpret_cast<void***>(GameRulesReferenceAddress);
}
g_pFunctionTable_Post->pfnServerDeactivate = FMH_ServerDeactivate_Post;
RETURN_META(MRES_IGNORED);
}

View File

@ -55,7 +55,8 @@ extern AMX_NATIVE_INFO engfunc_natives[];
extern AMX_NATIVE_INFO dllfunc_natives[];
extern AMX_NATIVE_INFO forward_natives[];
extern AMX_NATIVE_INFO pdata_natives[];
extern AMX_NATIVE_INFO pdata_gc_natives[];
extern AMX_NATIVE_INFO pdata_entities_natives[];
extern AMX_NATIVE_INFO pdata_gamerules_natives[];
extern AMX_NATIVE_INFO tr_Natives[];
extern AMX_NATIVE_INFO pev_natives[];
extern AMX_NATIVE_INFO glb_natives[];
@ -75,9 +76,11 @@ extern NEW_DLL_FUNCTIONS *g_pNewFunctionsTable;
extern NEW_DLL_FUNCTIONS *g_pNewFunctionsTable_Post;
extern IGameConfig *CommonConfig;
extern IGameConfig *GamerulesConfig;
extern IGameConfigManager *ConfigManager;
extern HLTypeConversion TypeConversion;
extern void *GameRulesAddress;
#endif //_FAKEMETA_INCLUDE_H

View File

@ -104,7 +104,8 @@
<ClCompile Include="..\pdata.cpp" />
<ClCompile Include="..\dllfunc.cpp" />
<ClCompile Include="..\engfunc.cpp" />
<ClCompile Include="..\pdata_gc.cpp" />
<ClCompile Include="..\pdata_entities.cpp" />
<ClCompile Include="..\pdata_gamerules.cpp" />
<ClCompile Include="..\pev.cpp" />
<ClCompile Include="..\forward.cpp" />
<ClCompile Include="..\glb.cpp" />
@ -122,6 +123,7 @@
<ClInclude Include="..\forwardmacros.h" />
<ClInclude Include="..\glb.h" />
<ClInclude Include="..\moduleconfig.h" />
<ClInclude Include="..\pdata_shared.h" />
<ClInclude Include="..\sdk\CString.h" />
<ClInclude Include="..\sdk\CVector.h" />
<ClInclude Include="..\..\..\public\sdk\amxxmodule.h" />

View File

@ -71,12 +71,15 @@
<ClCompile Include="..\..\..\public\sdk\amxxmodule.cpp">
<Filter>Module SDK\SDK Base</Filter>
</ClCompile>
<ClCompile Include="..\pdata_gc.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\..\public\memtools\MemoryUtils.cpp">
<Filter>Memtools</Filter>
</ClCompile>
<ClCompile Include="..\pdata_entities.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\pdata_gamerules.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\fakemeta_amxx.h">
@ -118,6 +121,9 @@
<ClInclude Include="..\..\..\public\memtools\MemoryUtils.h">
<Filter>Memtools</Filter>
</ClInclude>
<ClInclude Include="..\pdata_shared.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="..\..\..\plugins\include\fakemeta.inc">

View File

@ -0,0 +1,246 @@
// vim: set ts=4 sw=4 tw=99 noet:
//
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
// Copyright (C) The AMX Mod X Development Team.
//
// This software is licensed under the GNU General Public License, version 3 or higher.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
// https://alliedmods.net/amxmodx-license
//
// Fakemeta Module
//
#include "fakemeta_amxx.h"
#include "pdata_shared.h"
// native any:get_ent_data(entity, const class[], const member[], element = 0);
static cell AMX_NATIVE_CALL get_ent_data(AMX *amx, cell *params)
{
int entity = params[1];
CHECK_ENTITY(entity);
TypeDescription data;
GET_TYPE_DESCRIPTION(2, data, CommonConfig);
int element = params[4];
CHECK_DATA(data, element, BaseFieldType::Integer);
return PvData::GetInt(entity, data, element);
}
// native set_ent_data(entity, const class[], const member[], any:value, element = 0);
static cell AMX_NATIVE_CALL set_ent_data(AMX *amx, cell *params)
{
int entity = params[1];
CHECK_ENTITY(entity);
TypeDescription data;
GET_TYPE_DESCRIPTION(2, data, CommonConfig);
int element = params[5];
CHECK_DATA(data, element, BaseFieldType::Integer);
if (data.fieldType == FieldType::FIELD_STRUCTURE || data.fieldType == FieldType::FIELD_CLASS)
{
MF_LogError(amx, AMX_ERR_NATIVE, "Setting directly to a class or structure address is not available");
return 0;
}
PvData::SetInt(entity, data, params[4], element);
return 1;
}
// native Float:get_ent_data_float(entity, const class[], const member[], element = 0);
static cell AMX_NATIVE_CALL get_ent_data_float(AMX *amx, cell *params)
{
int entity = params[1];
CHECK_ENTITY(entity);
TypeDescription data;
GET_TYPE_DESCRIPTION(2, data, CommonConfig);
int element = params[4];
CHECK_DATA(data, element, BaseFieldType::Float);
return PvData::GetFloat(entity, data, element);
}
// native set_ent_data_float(entity, const classname[], const member[], Float:value, element = 0);
static cell AMX_NATIVE_CALL set_ent_data_float(AMX *amx, cell *params)
{
int entity = params[1];
CHECK_ENTITY(entity);
TypeDescription data;
GET_TYPE_DESCRIPTION(2, data, CommonConfig);
int element = params[5];
CHECK_DATA(data, element, BaseFieldType::Float);
PvData::SetFloat(entity, data, amx_ctof(params[4]), element);
return 1;
}
// native get_ent_data_vector(entity, const class[], const member[], Float:value[3], element = 0);
static cell AMX_NATIVE_CALL get_ent_data_vector(AMX *amx, cell *params)
{
int entity = params[1];
CHECK_ENTITY(entity);
TypeDescription data;
GET_TYPE_DESCRIPTION(2, data, CommonConfig);
int element = params[5];
CHECK_DATA(data, element, BaseFieldType::Vector);
PvData::GetVector(entity, data, MF_GetAmxAddr(amx, params[4]), element);
return 1;
}
// native set_ent_data_vector(entity, const class[], const member[], Float:value[3], element = 0);
static cell AMX_NATIVE_CALL set_ent_data_vector(AMX *amx, cell *params)
{
int entity = params[1];
CHECK_ENTITY(entity);
TypeDescription data;
GET_TYPE_DESCRIPTION(2, data, CommonConfig);
int element = params[5];
CHECK_DATA(data, element, BaseFieldType::Vector);
PvData::SetVector(entity, data, MF_GetAmxAddr(amx, params[4]), element);
return 1;
}
// native get_ent_data_entity(entity, const class[], const member[], element = 0);
static cell AMX_NATIVE_CALL get_ent_data_entity(AMX *amx, cell *params)
{
int entity = params[1];
CHECK_ENTITY(entity);
TypeDescription data;
GET_TYPE_DESCRIPTION(2, data, CommonConfig);
int element = params[4];
CHECK_DATA(data, element, BaseFieldType::Entity);
return PvData::GetEntity(entity, data, element);
}
// native set_ent_data_entity(entity, const class[], const member[], value, element = 0);
static cell AMX_NATIVE_CALL set_ent_data_entity(AMX *amx, cell *params)
{
int entity = params[1];
int value = params[4];
CHECK_ENTITY(entity);
if (value != -1)
{
CHECK_ENTITY(value);
}
TypeDescription data;
GET_TYPE_DESCRIPTION(2, data, CommonConfig);
int element = params[5];
CHECK_DATA(data, element, BaseFieldType::Entity);
PvData::SetEntity(entity, data, value, element);
return 1;
}
// native get_ent_data_string(entity, const class[], const member[], value[], maxlen, element = 0);
static cell AMX_NATIVE_CALL get_ent_data_string(AMX *amx, cell *params)
{
int entity = params[1];
CHECK_ENTITY(entity);
TypeDescription data;
GET_TYPE_DESCRIPTION(2, data, CommonConfig);
int element = params[6];
CHECK_DATA(data, element, BaseFieldType::String);
auto buffer = params[4];
auto maxlen = params[5];
auto string = PvData::GetString(entity, data, element);
if (data.fieldSize)
{
maxlen = ke::Min(maxlen, data.fieldSize);
}
return MF_SetAmxStringUTF8Char(amx, buffer, string ? string : "", string ? strlen(string) : 0, maxlen);
}
// native set_ent_data_string(entity, const class[], const member[], const value[], element = 0);
static cell AMX_NATIVE_CALL set_ent_data_string(AMX *amx, cell *params)
{
int entity = params[1];
CHECK_ENTITY(entity);
TypeDescription data;
GET_TYPE_DESCRIPTION(2, data, CommonConfig);
int element = params[5];
CHECK_DATA(data, element, BaseFieldType::String);
int length;
const char *value = MF_GetAmxString(amx, params[4], 0, &length);
return PvData::SetString(entity, data, value, length, element);
}
// native get_ent_data_size(const class[], const member[]);
static cell AMX_NATIVE_CALL get_ent_data_size(AMX *amx, cell *params)
{
TypeDescription data;
GET_TYPE_DESCRIPTION(1, data, CommonConfig);
return data.fieldSize;
}
// native find_ent_data_info(const class[], const member[], &FieldType:type = FIELD_NONE, &arraysize = 0, &bool:unsigned = false);
static cell AMX_NATIVE_CALL find_ent_data_info(AMX *amx, cell *params)
{
TypeDescription data;
GET_TYPE_DESCRIPTION(1, data, CommonConfig);
*MF_GetAmxAddr(amx, params[3]) = static_cast<cell>(data.fieldType);
*MF_GetAmxAddr(amx, params[4]) = ke::Max<int>(0, data.fieldSize);
*MF_GetAmxAddr(amx, params[5]) = data.fieldUnsigned != 0;
return data.fieldOffset;
}
AMX_NATIVE_INFO pdata_entities_natives[] =
{
{ "get_ent_data" , get_ent_data },
{ "set_ent_data" , set_ent_data },
{ "get_ent_data_float" , get_ent_data_float },
{ "set_ent_data_float" , set_ent_data_float },
{ "get_ent_data_vector" , get_ent_data_vector },
{ "set_ent_data_vector" , set_ent_data_vector },
{ "get_ent_data_entity" , get_ent_data_entity },
{ "set_ent_data_entity" , set_ent_data_entity },
{ "get_ent_data_string" , get_ent_data_string },
{ "set_ent_data_string" , set_ent_data_string },
{ "get_ent_data_size" , get_ent_data_size },
{ "find_ent_data_info" , find_ent_data_info },
{ nullptr , nullptr }
};

View File

@ -0,0 +1,240 @@
// vim: set ts=4 sw=4 tw=99 noet:
//
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
// Copyright (C) The AMX Mod X Development Team.
//
// This software is licensed under the GNU General Public License, version 3 or higher.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
// https://alliedmods.net/amxmodx-license
//
// Fakemeta Module
//
#include "fakemeta_amxx.h"
#include "pdata_shared.h"
// native any:get_gamerules_int(const class[], const member[], element = 0);
static cell AMX_NATIVE_CALL get_gamerules_int(AMX *amx, cell *params)
{
CHECK_GAMERULES();
TypeDescription data;
GET_TYPE_DESCRIPTION(1, data, GamerulesConfig);
int element = params[3];
CHECK_DATA(data, element, BaseFieldType::Integer);
return PvData::GetInt(GameRulesAddress, data, element);
}
// native set_gamerules_int(const class[], const member[], any:value, element = 0);
static cell AMX_NATIVE_CALL set_gamerules_int(AMX *amx, cell *params)
{
CHECK_GAMERULES();
TypeDescription data;
GET_TYPE_DESCRIPTION(1, data, GamerulesConfig);
int element = params[4];
CHECK_DATA(data, element, BaseFieldType::Integer);
if (data.fieldType == FieldType::FIELD_STRUCTURE || data.fieldType == FieldType::FIELD_CLASS)
{
MF_LogError(amx, AMX_ERR_NATIVE, "Setting directly to a class or structure address is not available");
return 0;
}
PvData::SetInt(GameRulesAddress, data, params[3], element);
return 0;
}
// native Float:get_gamerules_float(const class[], const member[], element = 0);
static cell AMX_NATIVE_CALL get_gamerules_float(AMX *amx, cell *params)
{
CHECK_GAMERULES();
TypeDescription data;
GET_TYPE_DESCRIPTION(1, data, GamerulesConfig);
int element = params[3];
CHECK_DATA(data, element, BaseFieldType::Float);
return PvData::GetFloat(GameRulesAddress, data, element);
}
// native set_gamerules_float(const class[], const member[], Float:value, element = 0);
static cell AMX_NATIVE_CALL set_gamerules_float(AMX *amx, cell *params)
{
CHECK_GAMERULES();
TypeDescription data;
GET_TYPE_DESCRIPTION(1, data, GamerulesConfig);
int element = params[4];
CHECK_DATA(data, element, BaseFieldType::Float);
PvData::SetFloat(GameRulesAddress, data, amx_ctof(params[3]), element);
return 1;
}
// native get_gamerules_vector(const class[], const member[], Float:value[3], element = 0);
static cell AMX_NATIVE_CALL get_gamerules_vector(AMX *amx, cell *params)
{
CHECK_GAMERULES();
TypeDescription data;
GET_TYPE_DESCRIPTION(1, data, GamerulesConfig);
int element = params[4];
CHECK_DATA(data, element, BaseFieldType::Vector);
PvData::GetVector(GameRulesAddress, data, MF_GetAmxAddr(amx, params[3]), element);
return 1;
}
// native set_gamerules_vector(const class[], const member[], Float:value[3], element = 0);
static cell AMX_NATIVE_CALL set_gamerules_vector(AMX *amx, cell *params)
{
CHECK_GAMERULES();
TypeDescription data;
GET_TYPE_DESCRIPTION(1, data, GamerulesConfig);
int element = params[4];
CHECK_DATA(data, element, BaseFieldType::Vector);
PvData::GetVector(GameRulesAddress, data, MF_GetAmxAddr(amx, params[3]), element);
return 1;
}
// native get_gamerules_entity(const class[], const member[], element = 0);
static cell AMX_NATIVE_CALL get_gamerules_entity(AMX *amx, cell *params)
{
CHECK_GAMERULES();
TypeDescription data;
GET_TYPE_DESCRIPTION(1, data, GamerulesConfig);
int element = params[3];
CHECK_DATA(data, element, BaseFieldType::Entity);
return PvData::GetEntity(GameRulesAddress, data, element);
}
// native set_gamerules_entity(const class[], const member[], value, element = 0);
static cell AMX_NATIVE_CALL set_gamerules_entity(AMX *amx, cell *params)
{
CHECK_GAMERULES();
int value = params[3];
if (value != -1)
{
CHECK_ENTITY(value);
}
TypeDescription data;
GET_TYPE_DESCRIPTION(1, data, GamerulesConfig);
int element = params[4];
CHECK_DATA(data, element, BaseFieldType::Entity);
PvData::SetEntity(GameRulesAddress, data, params[3], element);
return 0;
}
// native get_gamerules_string(const class[], const member[], value[], maxlen, element = 0);
static cell AMX_NATIVE_CALL get_gamerules_string(AMX *amx, cell *params)
{
CHECK_GAMERULES();
TypeDescription data;
GET_TYPE_DESCRIPTION(1, data, GamerulesConfig);
int element = params[5];
CHECK_DATA(data, element, BaseFieldType::String);
auto buffer = params[3];
auto maxlen = params[4];
auto string = PvData::GetString(GameRulesAddress, data, element);
if (data.fieldSize)
{
maxlen = ke::Min(maxlen, data.fieldSize);
}
return MF_SetAmxStringUTF8Char(amx, buffer, string ? string : "", string ? strlen(string) : 0, maxlen);
}
// native set_gamerules_string(const class[], const member[], const value[], element = 0);
static cell AMX_NATIVE_CALL set_gamerules_string(AMX *amx, cell *params)
{
CHECK_GAMERULES();
TypeDescription data;
GET_TYPE_DESCRIPTION(1, data, GamerulesConfig);
int element = params[4];
CHECK_DATA(data, element, BaseFieldType::String);
int length;
const char *value = MF_GetAmxString(amx, params[3], 0, &length);
return PvData::SetString(GameRulesAddress, data, value, length, element);
}
// native get_gamerules_size(const class[], const member[]);
static cell AMX_NATIVE_CALL get_gamerules_size(AMX *amx, cell *params)
{
CHECK_GAMERULES();
TypeDescription data;
GET_TYPE_DESCRIPTION(1, data, GamerulesConfig);
return data.fieldSize;
}
// native find_gamerules_info(const class[], const member[], &FieldType:type = FIELD_NONE, &arraysize = 0, &bool:unsigned = false);
static cell AMX_NATIVE_CALL find_gamerules_info(AMX *amx, cell *params)
{
CHECK_GAMERULES();
TypeDescription data;
GET_TYPE_DESCRIPTION(1, data, GamerulesConfig);
*MF_GetAmxAddr(amx, params[3]) = static_cast<cell>(data.fieldType);
*MF_GetAmxAddr(amx, params[4]) = ke::Max<int>(0, data.fieldSize);
*MF_GetAmxAddr(amx, params[5]) = data.fieldUnsigned != 0;
return data.fieldOffset;
}
AMX_NATIVE_INFO pdata_gamerules_natives[] =
{
{ "get_gamerules_int" , get_gamerules_int },
{ "set_gamerules_int" , set_gamerules_int },
{ "get_gamerules_float" , get_gamerules_float },
{ "set_gamerules_float" , set_gamerules_float },
{ "get_gamerules_vector", get_gamerules_vector },
{ "set_gamerules_vector", set_gamerules_vector },
{ "get_gamerules_entity", get_gamerules_entity },
{ "set_gamerules_entity", set_gamerules_entity },
{ "get_gamerules_string", get_gamerules_string },
{ "set_gamerules_string", set_gamerules_string },
{ "get_gamerules_size" , get_gamerules_size },
{ "find_gamerules_info" , find_gamerules_info },
{ nullptr , nullptr }
};

View File

@ -1,537 +0,0 @@
// vim: set ts=4 sw=4 tw=99 noet:
//
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
// Copyright (C) The AMX Mod X Development Team.
//
// This software is licensed under the GNU General Public License, version 3 or higher.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
// https://alliedmods.net/amxmodx-license
//
// Fakemeta Module
//
#include "fakemeta_amxx.h"
#include <amtl/am-algorithm.h>
enum class BaseFieldType
{
None,
Integer,
Float,
Vector,
Entity,
String,
};
static const char *BaseFieldTypeName[] =
{
"none",
"integer",
"float",
"vector",
"entity",
"string",
};
static BaseFieldType GetBaseDataType(TypeDescription &data)
{
switch (data.fieldType)
{
case FieldType::FIELD_INTEGER:
case FieldType::FIELD_STRINGINT:
case FieldType::FIELD_SHORT:
case FieldType::FIELD_CHARACTER:
case FieldType::FIELD_CLASS:
case FieldType::FIELD_STRUCTURE:
case FieldType::FIELD_POINTER:
case FieldType::FIELD_FUNCTION:
case FieldType::FIELD_BOOLEAN:
{
return BaseFieldType::Integer;
}
case FieldType::FIELD_FLOAT:
{
return BaseFieldType::Float;
}
case FieldType::FIELD_VECTOR:
{
return BaseFieldType::Vector;
}
case FieldType::FIELD_CLASSPTR:
case FieldType::FIELD_ENTVARS:
case FieldType::FIELD_EDICT:
case FieldType::FIELD_EHANDLE:
{
return BaseFieldType::Entity;
}
case FieldType::FIELD_STRINGPTR:
case FieldType::FIELD_STRING:
{
return BaseFieldType::String;
}
}
return BaseFieldType::None;
}
#define GET_TYPE_DESCRIPTION(position, data, baseType) \
int classLength, memberLength; \
const char *className = MF_GetAmxString(amx, params[position], 0, &classLength); \
const char *memberName = MF_GetAmxString(amx, params[position + 1], 1, &memberLength); \
if (!classLength || !memberLength) \
{ \
MF_LogError(amx, AMX_ERR_NATIVE, "Either class (\"%s\") or member (\"%s\") is empty", className, memberName); \
return 0; \
} \
else if (!CommonConfig->GetOffsetByClass(className, memberName, &data)) \
{ \
MF_LogError(amx, AMX_ERR_NATIVE, "Could not find class \"%s\" and/or member \"%s\" in gamedata", className, memberName); \
return 0; \
} \
else if (data.fieldOffset < 0) \
{ \
MF_LogError(amx, AMX_ERR_NATIVE, "Invalid offset %d retrieved from \"%s\" member", data.fieldOffset, memberName); \
return 0; \
} \
else if (baseType > BaseFieldType::None && baseType != GetBaseDataType(data)) \
{ \
MF_LogError(amx, AMX_ERR_NATIVE, "Data field is not %s-based", BaseFieldTypeName[static_cast<int>(baseType)]); \
return 0; \
}
#define CHECK_ELEMENT(element) \
if (element < 0 || (element > 0 && element >= data.fieldSize)) \
{ \
MF_LogError(amx, AMX_ERR_NATIVE, "Invalid element index %d, value must be between 0 and %d", element, data.fieldSize); \
return 0; \
} \
else if (element > 0 && !data.fieldSize) \
{ \
MF_LogError(amx, AMX_ERR_NATIVE, "Member \"%s\" is not an array. Element %d is invalid.", memberName, element);\
return 0; \
}
// native any:get_ent_data(entity, const class[], const member[], element = 0);
static cell AMX_NATIVE_CALL get_ent_data(AMX *amx, cell *params)
{
int entity = params[1];
CHECK_ENTITY(entity);
TypeDescription data;
GET_TYPE_DESCRIPTION(2, data, BaseFieldType::Integer);
int element = params[4];
CHECK_ELEMENT(element);
auto pEntity = TypeConversion.id_to_edict(entity);
switch (data.fieldType)
{
case FieldType::FIELD_INTEGER:
case FieldType::FIELD_STRINGINT:
{
return get_pdata<int32>(pEntity, data.fieldOffset, element);
}
case FieldType::FIELD_CLASS:
case FieldType::FIELD_STRUCTURE:
{
return reinterpret_cast<cell>(reinterpret_cast<int8*>(pEntity->pvPrivateData) + data.fieldOffset);
}
case FieldType::FIELD_POINTER:
case FieldType::FIELD_FUNCTION:
{
return reinterpret_cast<cell>(get_pdata<void*>(pEntity, data.fieldOffset, element));
}
case FieldType::FIELD_SHORT:
{
if (data.fieldUnsigned)
{
return get_pdata<uint16>(pEntity, data.fieldOffset, element);
}
else
{
return get_pdata<int16>(pEntity, data.fieldOffset, element);
}
}
case FieldType::FIELD_CHARACTER:
{
if (data.fieldUnsigned)
{
return get_pdata<uint8>(pEntity, data.fieldOffset, element);
}
else
{
return get_pdata<int8>(pEntity, data.fieldOffset, element);
}
}
case FieldType::FIELD_BOOLEAN:
{
return get_pdata<bool>(pEntity, data.fieldOffset, element) ? 1 : 0;
}
}
return 0;
}
// native set_ent_data(entity, const class[], const member[], any:value, element = 0);
static cell AMX_NATIVE_CALL set_ent_data(AMX *amx, cell *params)
{
int entity = params[1];
CHECK_ENTITY(entity);
TypeDescription data;
GET_TYPE_DESCRIPTION(2, data, BaseFieldType::Integer);
int element = params[5];
CHECK_ELEMENT(element);
auto pEntity = TypeConversion.id_to_edict(entity);
auto value = params[4];
switch (data.fieldType)
{
case FieldType::FIELD_INTEGER:
case FieldType::FIELD_STRINGINT:
{
set_pdata<int32>(pEntity, data.fieldOffset, static_cast<int32>(value), element);
break;
}
case FieldType::FIELD_CLASS:
case FieldType::FIELD_STRUCTURE:
{
MF_LogError(amx, AMX_ERR_NATIVE, "Setting directly to a class or structure address is not available");
return 0;
}
case FieldType::FIELD_POINTER:
case FieldType::FIELD_FUNCTION:
{
set_pdata<void*>(pEntity, data.fieldOffset, reinterpret_cast<void*>(value), element);
break;
}
case FieldType::FIELD_SHORT:
{
if (data.fieldUnsigned)
{
set_pdata<uint16>(pEntity, data.fieldOffset, static_cast<uint16>(value), element);
}
else
{
set_pdata<int16>(pEntity, data.fieldOffset, static_cast<uint16>(value), element);
}
break;
}
case FieldType::FIELD_CHARACTER:
{
if (data.fieldUnsigned)
{
set_pdata<uint8>(pEntity, data.fieldOffset, static_cast<uint8>(value), element);
}
else
{
set_pdata<int8>(pEntity, data.fieldOffset, static_cast<uint8>(value), element);
}
break;
}
case FieldType::FIELD_BOOLEAN:
{
set_pdata<bool>(pEntity, data.fieldOffset, value != 0, element);
break;
}
}
return 0;
}
// native Float:get_ent_data_float(entity, const class[], const member[], element = 0);
static cell AMX_NATIVE_CALL get_ent_data_float(AMX *amx, cell *params)
{
int entity = params[1];
CHECK_ENTITY(entity);
TypeDescription data;
GET_TYPE_DESCRIPTION(2, data, BaseFieldType::Float);
int element = params[4];
CHECK_ELEMENT(element);
return amx_ftoc(get_pdata<float>(TypeConversion.id_to_edict(entity), data.fieldOffset, element));
}
// native set_ent_data_float(entity, const classname[], const member[], Float:value, element = 0);
static cell AMX_NATIVE_CALL set_ent_data_float(AMX *amx, cell *params)
{
int entity = params[1];
CHECK_ENTITY(entity);
TypeDescription data;
GET_TYPE_DESCRIPTION(2, data, BaseFieldType::Float);
int element = params[5];
CHECK_ELEMENT(element);
set_pdata<float>(TypeConversion.id_to_edict(entity), data.fieldOffset, amx_ctof(params[4]), element);
return 1;
}
// native get_ent_data_vector(entity, const class[], const member[], Float:value[3], element = 0);
static cell AMX_NATIVE_CALL get_ent_data_vector(AMX *amx, cell *params)
{
int entity = params[1];
CHECK_ENTITY(entity);
TypeDescription data;
GET_TYPE_DESCRIPTION(2, data, BaseFieldType::Vector);
int element = params[5];
CHECK_ELEMENT(element);
auto refvec = MF_GetAmxAddr(amx, params[4]);
auto vector = get_pdata<Vector>(TypeConversion.id_to_edict(entity), data.fieldOffset, element);
refvec[0] = amx_ftoc(vector.x);
refvec[1] = amx_ftoc(vector.y);
refvec[2] = amx_ftoc(vector.z);
return 1;
}
// native set_ent_data_vector(entity, const class[], const member[], Float:value[3], element = 0);
static cell AMX_NATIVE_CALL set_ent_data_vector(AMX *amx, cell *params)
{
int entity = params[1];
CHECK_ENTITY(entity);
TypeDescription data;
GET_TYPE_DESCRIPTION(2, data, BaseFieldType::Vector);
int element = params[5];
CHECK_ELEMENT(element);
auto refvec = MF_GetAmxAddr(amx, params[4]);
Vector vector(amx_ctof(refvec[0]), amx_ctof(refvec[1]), amx_ctof(refvec[2]));
set_pdata<Vector>(TypeConversion.id_to_edict(entity), data.fieldOffset, vector, element);
return 1;
}
// native get_ent_data_entity(entity, const class[], const member[], element = 0);
static cell AMX_NATIVE_CALL get_ent_data_entity(AMX *amx, cell *params)
{
int entity = params[1];
CHECK_ENTITY(entity);
TypeDescription data;
GET_TYPE_DESCRIPTION(2, data, BaseFieldType::Entity);
int element = params[4];
CHECK_ELEMENT(element);
auto pEntity = TypeConversion.id_to_edict(entity);
switch (data.fieldType)
{
case FieldType::FIELD_CLASSPTR:
{
return TypeConversion.cbase_to_id(get_pdata<void*>(pEntity, data.fieldOffset, element));
}
case FieldType::FIELD_ENTVARS:
{
return TypeConversion.entvars_to_id(get_pdata<entvars_t*>(pEntity, data.fieldOffset, element));
}
case FieldType::FIELD_EDICT:
{
return TypeConversion.edict_to_id(get_pdata<edict_t*>(pEntity, data.fieldOffset, element));
}
case FieldType::FIELD_EHANDLE:
{
return TypeConversion.edict_to_id(get_pdata<EHANDLE>(pEntity, data.fieldOffset, element).Get());
}
}
return 0;
}
// native set_ent_data_entity(entity, const class[], const member[], value, element = 0);
static cell AMX_NATIVE_CALL set_ent_data_entity(AMX *amx, cell *params)
{
int entity = params[1];
int value = params[4];
CHECK_ENTITY(entity);
if (value != -1)
{
CHECK_ENTITY(value);
}
TypeDescription data;
GET_TYPE_DESCRIPTION(2, data, BaseFieldType::Entity);
int element = params[5];
CHECK_ELEMENT(element);
auto pEntity = TypeConversion.id_to_edict(entity);
switch (data.fieldType)
{
case FieldType::FIELD_CLASSPTR:
{
set_pdata<void*>(pEntity, data.fieldOffset, value != -1 ? TypeConversion.id_to_cbase(value) : nullptr, element);
break;
}
case FieldType::FIELD_ENTVARS:
{
set_pdata<entvars_t*>(pEntity, data.fieldOffset, value != -1 ? TypeConversion.id_to_entvars(value) : nullptr, element);
break;
}
case FieldType::FIELD_EDICT:
{
set_pdata<edict_t*>(pEntity, data.fieldOffset, value != -1 ? TypeConversion.id_to_edict(value) : nullptr, element);
break;
}
case FieldType::FIELD_EHANDLE:
{
get_pdata<EHANDLE>(pEntity, data.fieldOffset, element).Set(value != -1 ? TypeConversion.id_to_edict(value) : nullptr);
break;
}
}
return 0;
}
// native get_ent_data_string(entity, const class[], const member[], value[], maxlen, element = 0);
static cell AMX_NATIVE_CALL get_ent_data_string(AMX *amx, cell *params)
{
int entity = params[1];
CHECK_ENTITY(entity);
TypeDescription data;
GET_TYPE_DESCRIPTION(2, data, BaseFieldType::String);
int element = params[6];
CHECK_ELEMENT(element);
auto pEntity = TypeConversion.id_to_edict(entity);
cell buffer = params[4];
int maxlen = params[5];
switch (data.fieldType)
{
case FieldType::FIELD_STRING:
{
maxlen = ke::Min<int>(maxlen, static_cast<int>(data.fieldSize));
char *string = get_pdata_direct<char*>(pEntity, data.fieldOffset, element, data.fieldSize);
return MF_SetAmxStringUTF8Char(amx, buffer, string ? string : "", string ? strlen(string) : 0, maxlen);
}
case FieldType::FIELD_STRINGPTR:
{
char *string = get_pdata<char*>(pEntity, data.fieldOffset, element);
return MF_SetAmxStringUTF8Char(amx, buffer, string ? string : "", string ? strlen(string) : 0, maxlen);
}
}
return 0;
}
// native set_ent_data_string(entity, const class[], const member[], const value[], element = 0);
static cell AMX_NATIVE_CALL set_ent_data_string(AMX *amx, cell *params)
{
int entity = params[1];
CHECK_ENTITY(entity);
TypeDescription data;
GET_TYPE_DESCRIPTION(2, data, BaseFieldType::String);
int element = params[5];
CHECK_ELEMENT(element);
auto pEntity = TypeConversion.id_to_edict(entity);
int length;
const char *value = MF_GetAmxString(amx, params[4], 0, &length);
switch (data.fieldType)
{
case FieldType::FIELD_STRING:
{
auto buffer = reinterpret_cast<char*>(pEntity->pvPrivateData) + data.fieldOffset;
return strncopy(buffer, value, ke::Min<int>(length + 1, data.fieldSize));
}
case FieldType::FIELD_STRINGPTR:
{
auto buffer = get_pdata<char*>(pEntity, data.fieldOffset, element);
if (!buffer || length > static_cast<int>(strlen(buffer)))
{
if (buffer)
{
free(buffer);
}
buffer = reinterpret_cast<char*>(malloc(length + 1));
set_pdata<char*>(pEntity, data.fieldOffset, buffer, element);
}
return strncopy(buffer, value, length + 1);
}
}
return 0;
}
// native get_ent_data_size(const class[], const member[]);
static cell AMX_NATIVE_CALL get_ent_data_size(AMX *amx, cell *params)
{
TypeDescription data;
GET_TYPE_DESCRIPTION(0, data, BaseFieldType::None);
return data.fieldSize;
}
// native find_ent_data_info(const class[], const member[], &FieldType:type = FIELD_NONE, &arraysize = 0, &bool:unsigned = false);
static cell AMX_NATIVE_CALL find_ent_data_info(AMX *amx, cell *params)
{
TypeDescription data;
GET_TYPE_DESCRIPTION(1, data, BaseFieldType::None);
*MF_GetAmxAddr(amx, params[3]) = static_cast<cell>(data.fieldType);
*MF_GetAmxAddr(amx, params[4]) = ke::Max<int>(0, data.fieldSize);
*MF_GetAmxAddr(amx, params[5]) = data.fieldUnsigned != 0;
return data.fieldOffset;
}
AMX_NATIVE_INFO pdata_gc_natives[] =
{
{ "get_ent_data" , get_ent_data },
{ "set_ent_data" , set_ent_data },
{ "get_ent_data_float" , get_ent_data_float },
{ "set_ent_data_float" , set_ent_data_float },
{ "get_ent_data_vector", get_ent_data_vector },
{ "set_ent_data_vector", set_ent_data_vector },
{ "get_ent_data_entity", get_ent_data_entity },
{ "set_ent_data_entity", set_ent_data_entity },
{ "get_ent_data_string", get_ent_data_string },
{ "set_ent_data_string", set_ent_data_string },
{ "get_ent_data_size" , get_ent_data_size },
{ "find_ent_data_info" , find_ent_data_info },
{ nullptr , nullptr }
};

View File

@ -0,0 +1,419 @@
//
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
// Copyright (C) The AMX Mod X Development Team.
//
// This software is licensed under the GNU General Public License, version 3 or higher.
// Additional exceptions apply. For full license details, see LICENSE.txt or visit:
// https://alliedmods.net/amxmodx-license
#ifndef _PDATA_SHARED_H_
#define _PDATA_SHARED_H_
#include <amxxmodule.h>
#include <IGameConfigs.h>
#include <HLTypeConversion.h>
#include <amtl/am-algorithm.h>
extern HLTypeConversion TypeConversion;
enum class BaseFieldType
{
None,
Integer,
Float,
Vector,
Entity,
String,
};
#define GET_TYPE_DESCRIPTION(position, data, conf) \
int classLength, memberLength; \
char const *className = MF_GetAmxString(amx, params[position], 0, &classLength); \
char const *memberName = MF_GetAmxString(amx, params[position + 1], 1, &memberLength); \
if (!classLength || !memberLength) \
{ \
MF_LogError(amx, AMX_ERR_NATIVE, "Either class (\"%s\") or member (\"%s\") is empty", className, memberName); \
return 0; \
} \
else if (!conf->GetOffsetByClass(className, memberName, &data)) \
{ \
MF_LogError(amx, AMX_ERR_NATIVE, "Could not find class \"%s\" and/or member \"%s\" in gamedata", className, memberName); \
return 0; \
} \
else if (data.fieldOffset < 0) \
{ \
MF_LogError(amx, AMX_ERR_NATIVE, "Invalid offset %d retrieved from \"%s\" member", data.fieldOffset, memberName); \
return 0; \
}
#define CHECK_DATA(data, element, baseType) \
if (baseType > BaseFieldType::None && baseType != PvData::GetBaseDataType(data)) \
{ \
MF_LogError(amx, AMX_ERR_NATIVE, "Data field is not %s-based", PvData::GetBaseTypeName(baseType)); \
return 0; \
} \
else if (element < 0 || (element > 0 && element >= data.fieldSize)) \
{ \
MF_LogError(amx, AMX_ERR_NATIVE, "Invalid element index %d, value must be between 0 and %d", element, data.fieldSize); \
return 0; \
} \
else if (element > 0 && !data.fieldSize) \
{ \
MF_LogError(amx, AMX_ERR_NATIVE, "Member \"%s\" is not an array. Element %d is invalid.", memberName, element); \
return 0; \
}
#define CHECK_GAMERULES() \
if (!GameRulesAddress) \
{ \
MF_LogError(amx, AMX_ERR_NATIVE, "%s is disabled. Check your AMXX log.", __FUNCTION__); \
return 0; \
}
class PvData
{
public:
static cell GetInt(int index, TypeDescription &data, int element)
{
return GetInt(TypeConversion.id_to_edict(index)->pvPrivateData, data, element);
}
static cell GetInt(void *pObject, TypeDescription &data, int element)
{
switch (data.fieldType)
{
case FieldType::FIELD_INTEGER:
case FieldType::FIELD_STRINGINT:
{
return get_pdata<int32>(pObject, data.fieldOffset, element);
}
case FieldType::FIELD_CLASS:
case FieldType::FIELD_STRUCTURE:
{
return get_pdata_direct<cell>(pObject, data.fieldOffset);
}
case FieldType::FIELD_POINTER:
case FieldType::FIELD_FUNCTION:
{
return reinterpret_cast<cell>(get_pdata<void*>(pObject, data.fieldOffset, element));
}
case FieldType::FIELD_SHORT:
{
if (data.fieldUnsigned)
{
return get_pdata<uint16>(pObject, data.fieldOffset, element);
}
else
{
return get_pdata<int16>(pObject, data.fieldOffset, element);
}
}
case FieldType::FIELD_CHARACTER:
{
if (data.fieldUnsigned)
{
return get_pdata<uint8>(pObject, data.fieldOffset, element);
}
else
{
return get_pdata<int8>(pObject, data.fieldOffset, element);
}
}
case FieldType::FIELD_BOOLEAN:
{
return get_pdata<bool>(pObject, data.fieldOffset, element) ? 1 : 0;
}
}
return 0;
}
static void SetInt(int index, TypeDescription &data, cell value, int element)
{
SetInt(TypeConversion.id_to_edict(index)->pvPrivateData, data, value, element);
}
static void SetInt(void *pObject, TypeDescription &data, cell value, int element)
{
switch (data.fieldType)
{
case FieldType::FIELD_INTEGER:
case FieldType::FIELD_STRINGINT:
{
set_pdata<int32>(pObject, data.fieldOffset, static_cast<int32>(value), element);
break;
}
case FieldType::FIELD_POINTER:
case FieldType::FIELD_FUNCTION:
{
set_pdata<void*>(pObject, data.fieldOffset, reinterpret_cast<void*>(value), element);
break;
}
case FieldType::FIELD_SHORT:
{
if (data.fieldUnsigned)
{
set_pdata<uint16>(pObject, data.fieldOffset, static_cast<uint16>(value), element);
}
else
{
set_pdata<int16>(pObject, data.fieldOffset, static_cast<int16>(value), element);
}
break;
}
case FieldType::FIELD_CHARACTER:
{
if (data.fieldUnsigned)
{
set_pdata<uint8>(pObject, data.fieldOffset, static_cast<uint8>(value), element);
}
else
{
set_pdata<int8>(pObject, data.fieldOffset, static_cast<int8>(value), element);
}
break;
}
case FieldType::FIELD_BOOLEAN:
{
set_pdata<bool>(pObject, data.fieldOffset, value != 0, element);
break;
}
}
}
static cell GetFloat(int index, TypeDescription &data, int element)
{
return GetFloat(TypeConversion.id_to_edict(index)->pvPrivateData, data, element);
}
static cell GetFloat(void *pObject, TypeDescription &data, int element)
{
return amx_ftoc(get_pdata<float>(pObject, data.fieldOffset, element));
}
static void SetFloat(int index, TypeDescription &data, float value, int element)
{
SetFloat(TypeConversion.id_to_edict(index)->pvPrivateData, data, value, element);
}
static void SetFloat(void *pObject, TypeDescription &data, float value, int element)
{
set_pdata<float>(pObject, data.fieldOffset, value, element);
}
static void GetVector(int index, TypeDescription &data, cell *pVector, int element)
{
return GetVector(TypeConversion.id_to_edict(index)->pvPrivateData, data, pVector, element);
}
static void GetVector(void *pObject, TypeDescription &data, cell *pVector, int element)
{
auto vector = get_pdata<Vector>(pObject, data.fieldOffset, element);
pVector[0] = amx_ftoc(vector.x);
pVector[1] = amx_ftoc(vector.y);
pVector[2] = amx_ftoc(vector.z);
}
static void SetVector(int index, TypeDescription &data, cell *pVector, int element)
{
SetVector(TypeConversion.id_to_edict(index)->pvPrivateData, data, pVector, element);
}
static void SetVector(void *pObject, TypeDescription &data, cell *pVector, int element)
{
Vector vector(amx_ctof(pVector[0]), amx_ctof(pVector[1]), amx_ctof(pVector[2]));
set_pdata<Vector>(pObject, data.fieldOffset, vector, element);
}
static cell GetEntity(int index, TypeDescription &data, int element)
{
return GetEntity(TypeConversion.id_to_edict(index)->pvPrivateData, data, element);
}
static cell GetEntity(void *pObject, TypeDescription &data, int element)
{
switch (data.fieldType)
{
case FieldType::FIELD_CLASSPTR:
{
return TypeConversion.cbase_to_id(get_pdata<void*>(pObject, data.fieldOffset, element));
}
case FieldType::FIELD_ENTVARS:
{
return TypeConversion.entvars_to_id(get_pdata<entvars_t*>(pObject, data.fieldOffset, element));
}
case FieldType::FIELD_EDICT:
{
return TypeConversion.edict_to_id(get_pdata<edict_t*>(pObject, data.fieldOffset, element));
}
case FieldType::FIELD_EHANDLE:
{
return TypeConversion.edict_to_id(get_pdata<EHANDLE>(pObject, data.fieldOffset, element).Get());
}
}
return 0;
}
static void SetEntity(int index, TypeDescription &data, int value, int element)
{
SetEntity(TypeConversion.id_to_edict(index)->pvPrivateData, data, value, element);
}
static void SetEntity(void *pObject, TypeDescription &data, int value, int element)
{
switch (data.fieldType)
{
case FieldType::FIELD_CLASSPTR:
{
set_pdata<void*>(pObject, data.fieldOffset, value != -1 ? TypeConversion.id_to_cbase(value) : nullptr, element);
break;
}
case FieldType::FIELD_ENTVARS:
{
set_pdata<entvars_t*>(pObject, data.fieldOffset, value != -1 ? TypeConversion.id_to_entvars(value) : nullptr, element);
break;
}
case FieldType::FIELD_EDICT:
{
set_pdata<edict_t*>(pObject, data.fieldOffset, value != -1 ? TypeConversion.id_to_edict(value) : nullptr, element);
break;
}
case FieldType::FIELD_EHANDLE:
{
get_pdata<EHANDLE>(pObject, data.fieldOffset, element).Set(value != -1 ? TypeConversion.id_to_edict(value) : nullptr);
break;
}
}
}
static char* GetString(int index, TypeDescription &data, int element)
{
return GetString(TypeConversion.id_to_edict(index)->pvPrivateData, data, element);
}
static char* GetString(void *pObject, TypeDescription &data, int element)
{
switch (data.fieldType)
{
case FieldType::FIELD_STRING:
{
return get_pdata_direct<char*>(pObject, data.fieldOffset, element, data.fieldSize);
}
case FieldType::FIELD_STRINGPTR:
{
return get_pdata<char*>(pObject, data.fieldOffset, element);
}
}
return nullptr;
}
static cell SetString(int index, TypeDescription &data, const char *value, int maxlen, int element)
{
return SetString(TypeConversion.id_to_edict(index)->pvPrivateData, data, value, maxlen, element);
}
static cell SetString(void *pObject, TypeDescription &data, const char *value, int maxlen, int element)
{
switch (data.fieldType)
{
case FieldType::FIELD_STRING:
{
auto buffer = get_pdata_direct<char*>(pObject, data.fieldOffset);
return strncopy(buffer, value, ke::Min<int>(maxlen + 1, data.fieldSize));
}
case FieldType::FIELD_STRINGPTR:
{
auto buffer = get_pdata<char*>(pObject, data.fieldOffset, element);
if (!buffer || maxlen > static_cast<int>(strlen(buffer)))
{
if (buffer)
{
free(buffer);
}
buffer = reinterpret_cast<char*>(malloc(maxlen + 1));
set_pdata<char*>(pObject, data.fieldOffset, buffer, element);
}
return strncopy(buffer, value, maxlen + 1);
}
}
return 0;
}
public:
static BaseFieldType GetBaseDataType(TypeDescription &data)
{
switch (data.fieldType)
{
case FieldType::FIELD_INTEGER:
case FieldType::FIELD_STRINGINT:
case FieldType::FIELD_SHORT:
case FieldType::FIELD_CHARACTER:
case FieldType::FIELD_CLASS:
case FieldType::FIELD_STRUCTURE:
case FieldType::FIELD_POINTER:
case FieldType::FIELD_FUNCTION:
case FieldType::FIELD_BOOLEAN:
{
return BaseFieldType::Integer;
}
case FieldType::FIELD_FLOAT:
{
return BaseFieldType::Float;
}
case FieldType::FIELD_VECTOR:
{
return BaseFieldType::Vector;
}
case FieldType::FIELD_CLASSPTR:
case FieldType::FIELD_ENTVARS:
case FieldType::FIELD_EDICT:
case FieldType::FIELD_EHANDLE:
{
return BaseFieldType::Entity;
}
case FieldType::FIELD_STRINGPTR:
case FieldType::FIELD_STRING:
{
return BaseFieldType::String;
}
}
return BaseFieldType::None;
}
static const char* GetBaseTypeName(BaseFieldType baseType)
{
static const char *BaseFieldTypeName[] =
{
"none",
"integer",
"float",
"vector",
"entity",
"string",
};
return BaseFieldTypeName[static_cast<size_t>(baseType)];
}
};
#endif // _PDATA_SHARED_H_

View File

@ -809,7 +809,7 @@ native get_ent_data_string(entity, const class[], const member[], value[], maxle
native set_ent_data_string(entity, const class[], const member[], const value[], element = 0);
/**
* Retrieves the size of array of a class member.
* Retrieves the size of array of n entity class member.
*
* @param class Class name
* @param member Member name
@ -821,7 +821,7 @@ native set_ent_data_string(entity, const class[], const member[], const value[],
native get_ent_data_size(const class[], const member[]);
/**
* Finds an offset based off a class and member name.
* Finds a offset based off an entity class and member name.
*
* @param class Class name
* @param member Member name
@ -831,10 +831,215 @@ native get_ent_data_size(const class[], const member[]);
*
* @return Class member offset
* @error If either class or member is empty, no offset is found or an invalid
* offset is retrieved, an error will be thrown.
* offset is retrieved, an error will be thrown.
*/
native find_ent_data_info(const class[], const member[], &FieldType:type = FIELD_NONE, &arraysize = 0, &bool:unsigned = false);
/**
* Retrieves an integer value from the gamerules object based off a class
* and member name.
*
* @note This native is used to access the following (C++/engine) data types:
* integer, boolean, short, character, pointer, structure, class,
* stringint and function. Unsigned variants (if applicable) are supported
* and will be converted automatically.
*
* @param class Class name
* @param member Member name
* @param element Element to retrieve (starting from 0) if member is an array
*
* @return Integer value
* @error If member is empty, no offset is found or an invalid offset
* is retrieved, or the data type does not match, an error will
* be thrown.
*/
native any:get_gamerules_int(const class[], const member[], element = 0);
/**
* Sets an integer value to the gamerules objecta based off a class
* and member name.
*
* @note This native is used to access the following (C++/engine) data types:
* integer, boolean, short, character, pointer, stringint and function.
* Unsigned variants (if applicable) are supported and will be converted
* automatically.
*
* @param class Class name
* @param member Member name
* @param value Value to set
* @param element Element to set (starting from 0) if member is an array
*
* @noreturn
* @error If member is empty, no offset is found or an invalid offset
* is retrieved, or the data type does not match, an error will
* be thrown.
*/
native set_gamerules_int(const class[], const member[], any:value, element = 0);
/**
* Retrieves a float value from the gamerules object based off a class
* and member name.
*
* @param class Class name
* @param member Member name
* @param element Element to retrieve (starting from 0) if member is an array
*
* @return Float value
* @error If member is empty, no offset is found or an invalid offset
* is retrieved, or the data type does not match, an error will
* be thrown.
*/
native Float:get_gamerules_float(const class[], const member[], element = 0);
/**
* Sets a float value to the gamerules object based off a class
* and member name.
*
* @param class Class name
* @param member Member name
* @param value Value to set
* @param element Element to set (starting from 0) if member is an array
*
* @noreturn
* @error If member is empty, no offset is found or an invalid offset
* is retrieved, or the data type does not match, an error will
* be thrown.
*/
native set_gamerules_float(const class[], const member[], Float:value, element = 0);
/**
* Retrieves a vector from the gamerules object based off a class and member name.
*
* @param class Class name
* @param member Member name
* @param value Vector buffer to store data in
* @param element Element to retrieve (starting from 0) if member is an array
*
* @noreturn
* @error If member is empty, no offset is found or an invalid offset
* is retrieved, or the data type does not match, an error will
* be thrown.
*/
native get_gamerules_vector(const class[], const member[], Float:value[3], element = 0);
/**
* Sets a vector to the gamerules object based off a class and member name.
*
* @param class Class name
* @param member Member name
* @param value Vector to set
* @param element Element to set (starting from 0) if member is an array
*
* @noreturn
* @error If member is empty, no offset is found or an invalid offset
* is retrieved, or the data type does not match, an error will
* be thrown.
*/
native set_gamerules_vector(const class[], const member[], Float:value[3], element = 0);
/**
* Retrieves an entity index from the gamerules object based off a class
* and member name.
*
* @note This native is used to access the following (C++/engine) data types:
* classptr, entvars, edict and ehandle.
*
* @param class Class name
* @param member Member name
* @param element Element to retrieve (starting from 0) if member is an array
*
* @return Entity index if found, -1 otherwise
* @error If member is empty, no offset is found or an invalid offset
* is retrieved, or the data type does not match, an error will
* be thrown.
*/
native get_gamerules_entity(const class[], const member[], element = 0);
/**
* Sets an entity index to the gamerules object based off a class
* and member name.
*
* @note This native is used to access the following (C++/engine) data types:
* classptr, entvars, edict and ehandle.
* @note Pass -1 as value to act as C++ NULL.
*
* @param class Class name
* @param member Member name
* @param value Entity index to set
* @param element Element to set (starting from 0) if member is an array
*
* @noreturn
* @error If member is empty, no offset is found or an invalid offset
* is retrieved, or the data type does not match, an error will
* be thrown.
*/
native set_gamerules_entity(const class[], const member[], value, element = 0);
/**
* Retrieves a string from the gamerules object based off a class and member name.
*
* @note This native is used to access the following (C++/engine) data types:
* string, stringptr.
*
* @param class Class name
* @param member Member name
* @param value Buffer to store data in
* @param maxlen Maximum size of the buffer
* @param element Element to retrieve (starting from 0) if member is an array
*
* @return Number of cells written to buffer
* @error If member is empty, no offset is found or an invalid offset
* is retrieved, or the data type does not match, an error will
* be thrown.
*/
native get_gamerules_string(const class[], const member[], value[], maxlen, element = 0);
/**
* Sets a string to the gamerules object based off a class and member name.
*
* @note This native is used to access the following (C++/engine) data types:
* string, stringptr.
*
* @param class Class name
* @param member Member name
* @param value String to set
* @param element Element to set (starting from 0) if member is an array
*
* @return Number of cells written to buffer
* @error If member is empty, no offset is found or an invalid offset
* is retrieved, or the data type does not match, an error will
* be thrown.
*/
native set_gamerules_string(const class[], const member[], const value[], element = 0);
/**
* Retrieves the size of array of a gamerules class member.
*
* @param class Class name
* @param member Member name
*
* @return Size of array (in elements), otherwise 1 if member is not an array
* @error If either class or member is empty, no offset is found or an invalid
* offset is retrieved, an error will be thrown.
*/
native get_gamerules_size(const class[], const member[]);
/**
* Finds a gamerules offset based off a class and member name.
*
* @param class Class name
* @param member Member name
* @param type Optional variable to store member type in (FIELD_* constants)
* @param arraysize Optional variable to store array size in, if member is an array
* @param unsigned Optional variable to store whether member is unsigned (short and char types only)
*
* @return Class member offset
* @error If either class or member is empty, no offset is found or an invalid
* offset is retrieved, an error will be thrown.
*/
native find_gamerules_info(const class[], const member[], &FieldType:type = FIELD_NONE, &arraysize = 0, &bool:unsigned = false);
/**
* Returns the data field base type based off a specific field type.
*
@ -848,9 +1053,9 @@ native find_ent_data_info(const class[], const member[], &FieldType:type = FIELD
*
* @return Base field type (BASEFIELD_* constants)
*/
stock BaseFieldType:get_ent_data_basetype(FieldType:type, type_name[] = "", maxlen = 0)
stock BaseFieldType:get_field_basetype(FieldType:type, type_name[] = "", maxlen = 0)
{
static baseFieldTypeNames[BaseFieldType][] =
static const baseFieldTypeNames[BaseFieldType][] =
{
"none",
"integer",

View File

@ -19,11 +19,17 @@ template <typename T> static inline T& ref_pdata(void *pPrivateData, int offset,
}
template <typename T> inline T get_pdata_direct(void *pPrivateData, int offset, int element = 0, int size = 0)
{
return reinterpret_cast<T>(reinterpret_cast<int8*>(pPrivateData) + offset + (element * size));
}
template <typename T> inline T get_pdata_direct(edict_t *pEntity, int offset, int element = 0, int size = 0)
{
return reinterpret_cast<T>((reinterpret_cast<int8*>(pEntity->pvPrivateData) + offset + (element * size)));
return get_pdata_direct<T>(pEntity->pvPrivateData, offset, element, size);
}
template <typename T> inline T& get_pdata(void *pPrivateData, int offset, int element = 0)
{
return ref_pdata<T>(pPrivateData, offset, element);

View File

@ -29,6 +29,12 @@ folder_list = [
'base/addons/amxmodx/data/gamedata/common.games/hostages.games/cstrike',
'base/addons/amxmodx/data/gamedata/common.games/others.games',
'base/addons/amxmodx/data/gamedata/common.games/others.games/cstrike',
'base/addons/amxmodx/data/gamedata/common.games/gamerules.games',
'base/addons/amxmodx/data/gamedata/common.games/gamerules.games/cstrike',
'base/addons/amxmodx/data/gamedata/common.games/gamerules.games/dod',
'base/addons/amxmodx/data/gamedata/common.games/gamerules.games/tfc',
'base/addons/amxmodx/data/gamedata/common.games/gamerules.games/gearbox',
'base/addons/amxmodx/data/gamedata/common.games/gamerules.games/valve',
'base/addons/amxmodx/data/gamedata/modules.games',
'base/addons/amxmodx/data/lang',
'base/addons/amxmodx/dlls',
@ -1212,6 +1218,45 @@ CopyFiles('gamedata/common.games/entities.games/valve', 'base/addons/amxmodx/dat
]
)
CopyFiles('gamedata/common.games/gamerules.games/cstrike', 'base/addons/amxmodx/data/gamedata/common.games/gamerules.games/cstrike',
[
'offsets-cgamerules.txt',
'offsets-chalflifemultiplay.txt',
'offsets-chalflifetraining.txt',
]
)
CopyFiles('gamedata/common.games/gamerules.games/dod', 'base/addons/amxmodx/data/gamedata/common.games/gamerules.games/dod',
[
'offsets-cdodteamplay.txt',
'offsets-cspdodrules.txt',
]
)
CopyFiles('gamedata/common.games/gamerules.games/gearbox', 'base/addons/amxmodx/data/gamedata/common.games/gamerules.games/gearbox',
[
'offsets-chalflifecoopplay.txt',
'offsets-chalflifectfplay.txt',
'offsets-chalflifemultiplay.txt',
'offsets-chalflifeteamplay.txt',
]
)
CopyFiles('gamedata/common.games/gamerules.games/tfc', 'base/addons/amxmodx/data/gamedata/common.games/gamerules.games/tfc',
[
'offsets-chalflifemultiplay.txt',
'offsets-chalflifeteamplay.txt',
'offsets-cteamfortress.txt',
]
)
CopyFiles('gamedata/common.games/gamerules.games/valve', 'base/addons/amxmodx/data/gamedata/common.games/gamerules.games/valve',
[
'offsets-chalflifemultiplay.txt',
'offsets-chalflifeteamplay.txt',
]
)
# Copy license files
licenses = [
'ACKNOWLEDGEMENTS.txt',