From 66af18ae5a1905529e81f4aec8ff5eecd6dac6d1 Mon Sep 17 00:00:00 2001 From: KitRifty Date: Thu, 28 Dec 2023 17:34:15 +0000 Subject: [PATCH 1/4] Add CTakeDamageInfo natives Add CBaseEntity.TakeDamageInfo native - Added signature to gamedata Add CTakeDamageInfo.Set native Add GetGlobalDamageInfo native Imported Init and Set CTakeDamage funcs from SDK Fix CTakeDamageInfo.AddDamageType missing parameter Fix some CTakeDamageInfo natives not returning immediately after erroring --- extension/natives/baseentity.cpp | 19 ++++- extension/natives/takedamageinfo.cpp | 77 +++++++++++++++++-- extension/sourcesdk/baseentity.cpp | 7 ++ extension/sourcesdk/baseentity.h | 3 + extension/sourcesdk/takedamageinfo.cpp | 52 +++++++++++++ gamedata/cbasenpc.txt | 7 ++ scripting/include/cbasenpc/baseentity.inc | 12 +++ scripting/include/cbasenpc/takedamageinfo.inc | 29 ++++++- 8 files changed, 198 insertions(+), 8 deletions(-) diff --git a/extension/natives/baseentity.cpp b/extension/natives/baseentity.cpp index b718e0a..c6f506e 100644 --- a/extension/natives/baseentity.cpp +++ b/extension/natives/baseentity.cpp @@ -510,6 +510,22 @@ cell_t IsCombatCharacter(IPluginContext* context, const cell_t* params) { return entity->MyCombatCharacterPointer() ? 1 : 0; } +cell_t TakeDamage(IPluginContext* context, const cell_t* params) { + auto entity = Get(context, params[1]); + if (!entity) { + return 0; + } + + CTakeDamageInfo* inputInfo = (CTakeDamageInfo*)PawnAddressToPtr(params[2]); + if (!inputInfo) { + context->ThrowNativeError("CTakeDamageInfo is a null ptr!"); + return 0; + } + + entity->TakeDamage(*inputInfo); + return 0; +} + void setup(std::vector& natives) { sp_nativeinfo_t list[] = { {"CBaseEntity.iUpdateOnRemove", iUpdateOnRemove}, @@ -554,7 +570,8 @@ void setup(std::vector& natives) { {"CBaseEntity.MyNextBotPointer", MyNextBotPointer}, {"CBaseEntity.GetBaseAnimating", GetBaseAnimating}, {"CBaseEntity.MyCombatCharacterPointer", MyCombatCharacterPointer}, - {"CBaseEntity.IsCombatCharacter", IsCombatCharacter} + {"CBaseEntity.IsCombatCharacter", IsCombatCharacter}, + {"CBaseEntity.TakeDamage", TakeDamage} }; natives.insert(natives.end(), std::begin(list), std::end(list)); } diff --git a/extension/natives/takedamageinfo.cpp b/extension/natives/takedamageinfo.cpp index 9280beb..b2d4c49 100644 --- a/extension/natives/takedamageinfo.cpp +++ b/extension/natives/takedamageinfo.cpp @@ -13,10 +13,10 @@ #include extern SourceMod::IGameHelpers* gamehelpers; -CTakeDamageInfo::CTakeDamageInfo(){} - namespace natives::takedamageinfo { +CTakeDamageInfo g_GlobalDamageInfo; + inline CTakeDamageInfo* Get(IPluginContext* context, const cell_t param) { CTakeDamageInfo* info = (CTakeDamageInfo*)PawnAddressToPtr(param); if (!info) { @@ -30,6 +30,69 @@ cell_t CTakeDamageInfo_Ctor(IPluginContext* context, const cell_t* params) { return PtrToPawnAddress(PawnAddressToPtr(params[1])); } +cell_t GetGlobalDamageInfo(IPluginContext* context, const cell_t* params) { + return PtrToPawnAddress(&g_GlobalDamageInfo); +} + +cell_t Set(IPluginContext* context, const cell_t* params) { + CTakeDamageInfo* info = Get(context, params[1]); + if (!info) { + return 0; + } + + CBaseEntity* inflictor = gamehelpers->ReferenceToEntity(params[2]); + if (!inflictor && params[2] != -1) { + return context->ThrowNativeError("Invalid inflictor index!"); + } + + CBaseEntity* attacker = gamehelpers->ReferenceToEntity(params[3]); + if (!attacker && params[3] != -1) { + return context->ThrowNativeError("Invalid attacker index!"); + } + + CBaseEntity* weapon = gamehelpers->ReferenceToEntity(params[4]); + if (!attacker && params[4] != -1) { + return context->ThrowNativeError("Invalid weapon index!"); + } + + cell_t *damageForceAddr; + context->LocalToPhysAddr(params[5], &damageForceAddr); + Vector damageForce; + if (context->GetNullRef(SP_NULL_VECTOR) == damageForceAddr) { + damageForce = vec3_origin; + } + else { + PawnVectorToVector(damageForceAddr, &damageForce); + } + + cell_t *damagePositionAddr; + context->LocalToPhysAddr(params[6], &damagePositionAddr); + Vector damagePosition; + if (context->GetNullRef(SP_NULL_VECTOR) == damagePositionAddr) { + damagePosition = vec3_origin; + } + else { + PawnVectorToVector(damagePositionAddr, &damagePosition); + } + + float damage = sp_ctof(params[7]); + int bitsDamageType = params[8]; + int customDamage = params[9]; + + cell_t *reportedPositionAddr; + context->LocalToPhysAddr(params[10], &reportedPositionAddr); + Vector reportedPosition; + if (context->GetNullRef(SP_NULL_VECTOR) == reportedPositionAddr) { + reportedPosition = vec3_origin; + } + else { + PawnVectorToVector(reportedPositionAddr, &reportedPosition); + } + + info->Set(inflictor, attacker, weapon, damageForce, damagePosition, damage, bitsDamageType, customDamage, &reportedPosition); + return 0; +} + cell_t GetInflictor(IPluginContext* context, const cell_t* params) { CTakeDamageInfo* info = Get(context, params[1]); if (!info) { @@ -47,7 +110,7 @@ cell_t SetInflictor(IPluginContext* context, const cell_t* params) { CBaseEntity* inflictor = gamehelpers->ReferenceToEntity(params[2]); if (!inflictor && params[2] != -1) { - context->ThrowNativeError("Invalid inflictor index!"); + return context->ThrowNativeError("Invalid inflictor index!"); } info->m_hInflictor = inflictor; return 0; @@ -70,7 +133,7 @@ cell_t SetWeapon(IPluginContext* context, const cell_t* params) { CBaseEntity* weapon = gamehelpers->ReferenceToEntity(params[2]); if (!weapon && params[2] != -1) { - context->ThrowNativeError("Invalid weapon index!"); + return context->ThrowNativeError("Invalid weapon index!"); } info->m_hWeapon = weapon; return 0; @@ -90,7 +153,7 @@ cell_t SetAttacker(IPluginContext* context, const cell_t* params) { CBaseEntity* attacker = gamehelpers->ReferenceToEntity(params[2]); if (!attacker && params[2] != -1) { - context->ThrowNativeError("Invalid attacker index!"); + return context->ThrowNativeError("Invalid attacker index!"); } info->m_hAttacker = attacker; return 0; @@ -503,6 +566,10 @@ void setup(std::vector& natives) { sp_nativeinfo_t list[] = { {"CTakeDamageInfo.CTakeDamageInfo", CTakeDamageInfo_Ctor}, + {"GetGlobalDamageInfo", GetGlobalDamageInfo}, + + {"CTakeDamageInfo.Set", Set}, + {"CTakeDamageInfo.GetInflictor", GetInflictor}, {"CTakeDamageInfo.SetInflictor", SetInflictor}, diff --git a/extension/sourcesdk/baseentity.cpp b/extension/sourcesdk/baseentity.cpp index 13da12c..8e538af 100644 --- a/extension/sourcesdk/baseentity.cpp +++ b/extension/sourcesdk/baseentity.cpp @@ -23,6 +23,7 @@ VCall CBaseEntity::vGetBaseAnimating; VCall CBaseEntity::vMyNextBotPointer; MCall CBaseEntity::mInvalidatePhysicsRecursive; VCall CBaseEntity::vWorldSpaceCenter; +MCall CBaseEntity::mTakeDamage; VCall CBaseEntity::vOnTakeDamage; VCall CBaseEntity::vIsAlive; MCall CBaseEntity::mCalcAbsolutePosition; @@ -120,6 +121,7 @@ bool CBaseEntity::Init(SourceMod::IGameConfig* config, char* error, size_t maxle vMyNextBotPointer.Init(config, "CBaseEntity::MyNextBotPointer"); vWorldSpaceCenter.Init(config, "CBaseEntity::WorldSpaceCenter"); vEyeAngles.Init(config, "CBaseEntity::EyeAngles"); + mTakeDamage.Init(config, "CBaseEntity::TakeDamage"); vOnTakeDamage.Init(configSDKHooks, "OnTakeDamage"); vIsAlive.Init(config, "CBaseEntity::IsAlive"); @@ -303,6 +305,11 @@ const Vector& CBaseEntity::WorldSpaceCenter(void) return vWorldSpaceCenter(this); } +void CBaseEntity::TakeDamage(const CTakeDamageInfo& inputInfo) +{ + return mTakeDamage(this, inputInfo); +} + int CBaseEntity::OnTakeDamage(const CTakeDamageInfo& info) { return vOnTakeDamage(this, info); diff --git a/extension/sourcesdk/baseentity.h b/extension/sourcesdk/baseentity.h index bb338a7..5841714 100644 --- a/extension/sourcesdk/baseentity.h +++ b/extension/sourcesdk/baseentity.h @@ -146,6 +146,9 @@ class CBaseEntity : public IServerEntity void CalcAbsolutePosition(void); void CalcAbsoluteVelocity(void); + static MCall mTakeDamage; + void TakeDamage(const CTakeDamageInfo &inputInfo); + static VCall vOnTakeDamage; int OnTakeDamage(const CTakeDamageInfo& info); diff --git a/extension/sourcesdk/takedamageinfo.cpp b/extension/sourcesdk/takedamageinfo.cpp index bfd2853..8473211 100644 --- a/extension/sourcesdk/takedamageinfo.cpp +++ b/extension/sourcesdk/takedamageinfo.cpp @@ -2,6 +2,58 @@ #include #include +CTakeDamageInfo::CTakeDamageInfo() +{ + Init( NULL, NULL, NULL, vec3_origin, vec3_origin, vec3_origin, 0, 0, 0 ); +} + +void CTakeDamageInfo::Init( CBaseEntity *pInflictor, CBaseEntity *pAttacker, CBaseEntity *pWeapon, const Vector &damageForce, const Vector &damagePosition, const Vector &reportedPosition, float flDamage, int bitsDamageType, int iCustomDamage ) +{ + m_hInflictor = pInflictor; + if ( pAttacker ) + { + m_hAttacker = pAttacker; + } + else + { + m_hAttacker = pInflictor; + } + + m_hWeapon = pWeapon; + + m_flDamage = flDamage; + + m_flBaseDamage = BASEDAMAGE_NOT_SPECIFIED; + + m_bitsDamageType = bitsDamageType; + m_iDamageCustom = iCustomDamage; + + m_flMaxDamage = flDamage; + m_vecDamageForce = damageForce; + m_vecDamagePosition = damagePosition; + m_vecReportedPosition = reportedPosition; + m_iAmmoType = -1; + m_iDamagedOtherPlayers = 0; + m_iPlayerPenetrationCount = 0; + m_flDamageBonus = 0.f; + m_bForceFriendlyFire = false; + m_flDamageForForce = 0.f; + +#if SOURCE_ENGINE == SE_TF2 + m_eCritType = kCritType_None; +#endif +} + +void CTakeDamageInfo::Set( CBaseEntity *pInflictor, CBaseEntity *pAttacker, CBaseEntity *pWeapon, const Vector &damageForce, const Vector &damagePosition, float flDamage, int bitsDamageType, int iKillType, Vector *reportedPosition ) +{ + Vector vecReported = vec3_origin; + if ( reportedPosition ) + { + vecReported = *reportedPosition; + } + Init( pInflictor, pAttacker, pWeapon, damageForce, damagePosition, vecReported, flDamage, bitsDamageType, iKillType ); +} + #if SOURCE_ENGINE == SE_TF2 void CTakeDamageInfo::SetCritType( ECritType eType ) { diff --git a/gamedata/cbasenpc.txt b/gamedata/cbasenpc.txt index 55dc86c..0a48c3b 100644 --- a/gamedata/cbasenpc.txt +++ b/gamedata/cbasenpc.txt @@ -268,6 +268,13 @@ "windows" "" "linux" "@_ZN11CBaseEntity15SetGroundEntityEPS_" } + // Find string "CBaseEntity::TakeDamage: with inputInfo.GetDamageForce() == vec3_origin\n" + "CBaseEntity::TakeDamage" + { + "library" "server" + "windows" "\x55\x8B\xEC\x81\xEC\x98\x00\x00\x00\x53\x8B\xD9" + "linux" "@_ZN11CBaseEntity10TakeDamageERK15CTakeDamageInfo" + } // "g_EntityListPool" "g_EntityListPool" { diff --git a/scripting/include/cbasenpc/baseentity.inc b/scripting/include/cbasenpc/baseentity.inc index ce07df1..26d5f86 100644 --- a/scripting/include/cbasenpc/baseentity.inc +++ b/scripting/include/cbasenpc/baseentity.inc @@ -3,6 +3,8 @@ #endif #define _CBASENPC_BASEENTITY_INC_ +#include "takedamageinfo.inc" + methodmap CBaseEntity { public CBaseEntity(int iEnt) @@ -910,4 +912,14 @@ methodmap CBaseEntity { SetEntityMoveType(this.index, val); } + + /** + * Causes the entity to take damage with the given parameters. + * Filters are checked and damage scaling is applied before it calls the + * entity's OnTakeDamage(). + * + * @param inputInfo The damage parameters to use + * @error Invalid entity or a NULL pointer is given + */ + public native void TakeDamage(CTakeDamageInfo inputInfo); } \ No newline at end of file diff --git a/scripting/include/cbasenpc/takedamageinfo.inc b/scripting/include/cbasenpc/takedamageinfo.inc index b98be71..cdab131 100644 --- a/scripting/include/cbasenpc/takedamageinfo.inc +++ b/scripting/include/cbasenpc/takedamageinfo.inc @@ -19,6 +19,22 @@ methodmap CTakeDamageInfo */ public native CTakeDamageInfo(Address ptr); + /** + * Initializes the CTakeDamageInfo's values. + * + * @param inflictor The inflictor entity index. + * @param attacker The attacker entity index. + * @param weapon The weapon entity index. + * @param damageForce The damage force vector. + * @param damagePosition The damage position vector. + * @param damage The amount of damage to set. + * @param bitsDamageType The damage type bitmask. + * @param customDamage The custom damage to set. + * @param reportedPosition The position to report to players on where the damage came from. + * @error Invalid takedamageinfo, or invalid inflictor, attacker, and weapon entity index. + */ + public native void Set(int inflictor = -1, int attacker = -1, int weapon = -1, const float damageForce[3] = NULL_VECTOR, const float damagePosition[3] = NULL_VECTOR, float damage = 0.0, int bitsDamageType = 0, int customDamage = 0, const float reportedPosition[3] = NULL_VECTOR); + /** * Gets the inflictor. * @@ -257,7 +273,7 @@ methodmap CTakeDamageInfo * @param bitmask The damage type bitmask to add. * @error Invalid takedamageinfo. */ - public native int AddDamageType(); + public native int AddDamageType(int bitmask); /** * Gets the custom damage. @@ -370,4 +386,13 @@ methodmap CTakeDamageInfo * @error Invalid takedamageinfo. */ public native TakeDamageInfo_CritType GetCritType(); -}; \ No newline at end of file +}; + +/** + * Returns the address of a global CTakeDamageInfo object. Make sure to + * initialize the values of the object first using CTakeDamageInfo.Set() + * before modifying and using it in a function call. + * + * @return Address to the global CTakeDamageInfo object. + */ +native CTakeDamageInfo GetGlobalDamageInfo(); \ No newline at end of file From 35965b5d688e6f51c1627e3506f0f8c473e8ffed Mon Sep 17 00:00:00 2001 From: KitRifty Date: Thu, 28 Dec 2023 17:54:35 +0000 Subject: [PATCH 2/4] Fix --- scripting/include/cbasenpc/takedamageinfo.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripting/include/cbasenpc/takedamageinfo.inc b/scripting/include/cbasenpc/takedamageinfo.inc index cdab131..235abae 100644 --- a/scripting/include/cbasenpc/takedamageinfo.inc +++ b/scripting/include/cbasenpc/takedamageinfo.inc @@ -265,7 +265,7 @@ methodmap CTakeDamageInfo * @param bitmask The damage type bitmask. * @error Invalid takedamageinfo. */ - public native int SetDamageType(); + public native int SetDamageType(int bitmask); /** * Adds the damage bitmask to the current damage bitmask. From 1ba99ed8663ba9134f4e3a27909574c67528874f Mon Sep 17 00:00:00 2001 From: KitRifty Date: Thu, 28 Dec 2023 18:10:32 +0000 Subject: [PATCH 3/4] Review changes --- extension/natives/takedamageinfo.cpp | 10 +++++----- extension/sourcesdk/baseentity.h | 2 +- scripting/include/cbasenpc/takedamageinfo.inc | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/extension/natives/takedamageinfo.cpp b/extension/natives/takedamageinfo.cpp index b2d4c49..b4615d4 100644 --- a/extension/natives/takedamageinfo.cpp +++ b/extension/natives/takedamageinfo.cpp @@ -34,7 +34,7 @@ cell_t GetGlobalDamageInfo(IPluginContext* context, const cell_t* params) { return PtrToPawnAddress(&g_GlobalDamageInfo); } -cell_t Set(IPluginContext* context, const cell_t* params) { +cell_t Init(IPluginContext* context, const cell_t* params) { CTakeDamageInfo* info = Get(context, params[1]); if (!info) { return 0; @@ -55,7 +55,7 @@ cell_t Set(IPluginContext* context, const cell_t* params) { return context->ThrowNativeError("Invalid weapon index!"); } - cell_t *damageForceAddr; + cell_t* damageForceAddr; context->LocalToPhysAddr(params[5], &damageForceAddr); Vector damageForce; if (context->GetNullRef(SP_NULL_VECTOR) == damageForceAddr) { @@ -65,7 +65,7 @@ cell_t Set(IPluginContext* context, const cell_t* params) { PawnVectorToVector(damageForceAddr, &damageForce); } - cell_t *damagePositionAddr; + cell_t* damagePositionAddr; context->LocalToPhysAddr(params[6], &damagePositionAddr); Vector damagePosition; if (context->GetNullRef(SP_NULL_VECTOR) == damagePositionAddr) { @@ -79,7 +79,7 @@ cell_t Set(IPluginContext* context, const cell_t* params) { int bitsDamageType = params[8]; int customDamage = params[9]; - cell_t *reportedPositionAddr; + cell_t* reportedPositionAddr; context->LocalToPhysAddr(params[10], &reportedPositionAddr); Vector reportedPosition; if (context->GetNullRef(SP_NULL_VECTOR) == reportedPositionAddr) { @@ -568,7 +568,7 @@ void setup(std::vector& natives) { {"GetGlobalDamageInfo", GetGlobalDamageInfo}, - {"CTakeDamageInfo.Set", Set}, + {"CTakeDamageInfo.Init", Init}, {"CTakeDamageInfo.GetInflictor", GetInflictor}, {"CTakeDamageInfo.SetInflictor", SetInflictor}, diff --git a/extension/sourcesdk/baseentity.h b/extension/sourcesdk/baseentity.h index 5841714..96edc32 100644 --- a/extension/sourcesdk/baseentity.h +++ b/extension/sourcesdk/baseentity.h @@ -147,7 +147,7 @@ class CBaseEntity : public IServerEntity void CalcAbsoluteVelocity(void); static MCall mTakeDamage; - void TakeDamage(const CTakeDamageInfo &inputInfo); + void TakeDamage(const CTakeDamageInfo& inputInfo); static VCall vOnTakeDamage; int OnTakeDamage(const CTakeDamageInfo& info); diff --git a/scripting/include/cbasenpc/takedamageinfo.inc b/scripting/include/cbasenpc/takedamageinfo.inc index 235abae..2e53d64 100644 --- a/scripting/include/cbasenpc/takedamageinfo.inc +++ b/scripting/include/cbasenpc/takedamageinfo.inc @@ -33,7 +33,7 @@ methodmap CTakeDamageInfo * @param reportedPosition The position to report to players on where the damage came from. * @error Invalid takedamageinfo, or invalid inflictor, attacker, and weapon entity index. */ - public native void Set(int inflictor = -1, int attacker = -1, int weapon = -1, const float damageForce[3] = NULL_VECTOR, const float damagePosition[3] = NULL_VECTOR, float damage = 0.0, int bitsDamageType = 0, int customDamage = 0, const float reportedPosition[3] = NULL_VECTOR); + public native void Init(int inflictor = -1, int attacker = -1, int weapon = -1, const float damageForce[3] = NULL_VECTOR, const float damagePosition[3] = NULL_VECTOR, float damage = 0.0, int bitsDamageType = 0, int customDamage = 0, const float reportedPosition[3] = NULL_VECTOR); /** * Gets the inflictor. @@ -390,7 +390,7 @@ methodmap CTakeDamageInfo /** * Returns the address of a global CTakeDamageInfo object. Make sure to - * initialize the values of the object first using CTakeDamageInfo.Set() + * initialize the values of the object first using CTakeDamageInfo.Init() * before modifying and using it in a function call. * * @return Address to the global CTakeDamageInfo object. From 3ae052a13dab8563c0b888797a53eeb1e1867002 Mon Sep 17 00:00:00 2001 From: Benoist <14257866+Kenzzer@users.noreply.github.com> Date: Thu, 28 Dec 2023 23:25:44 +0100 Subject: [PATCH 4/4] Update product.version --- product.version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/product.version b/product.version index 62321af..1cac385 100644 --- a/product.version +++ b/product.version @@ -1 +1 @@ -1.10.3 \ No newline at end of file +1.11.0