diff --git a/gamedata/tf2.utils.nosoop.txt b/gamedata/tf2.utils.nosoop.txt index cd22605..c9b3c5f 100644 --- a/gamedata/tf2.utils.nosoop.txt +++ b/gamedata/tf2.utils.nosoop.txt @@ -5,6 +5,11 @@ "Offsets" { // virtual offsets + "CBaseCombatCharacter::Weapon_ShootPosition()" + { + "windows" "268" + "linux" "269" + } "CBaseCombatWeapon::GetSlot()" { "windows" "326" diff --git a/scripting/include/tf2utils.inc b/scripting/include/tf2utils.inc index a376ceb..c6b4eec 100644 --- a/scripting/include/tf2utils.inc +++ b/scripting/include/tf2utils.inc @@ -48,6 +48,11 @@ native int TF2Util_GetPlayerMaxAmmo(int client, int iAmmoIndex, native int TF2Util_GetPlayerMaxHealth(int client, bool bIgnoreAttributes = false, bool bIgnoreOverheal = false); +/** + * Returns the player's shoot position. + */ +native void TF2Util_GetPlayerShootPosition(int client, float result[3]); + /** * Returns whether or not the given entity is a weapon. * diff --git a/scripting/tf2utils.sp b/scripting/tf2utils.sp index 368ec65..e5eb986 100644 --- a/scripting/tf2utils.sp +++ b/scripting/tf2utils.sp @@ -11,7 +11,7 @@ #include -#define PLUGIN_VERSION "0.8.0" +#define PLUGIN_VERSION "0.9.0" public Plugin myinfo = { name = "TF2 Utils", author = "nosoop", @@ -25,6 +25,7 @@ bool g_bDeferredSpeedUpdate[MAXPLAYERS + 1]; Handle g_SDKCallPlayerGetMaxAmmo; Handle g_SDKCallPlayerTakeHealth; +Handle g_SDKCallPlayerGetShootPosition; Handle g_SDKCallPlayerSharedGetMaxHealth; @@ -51,6 +52,8 @@ public APLRes AskPluginLoad2(Handle self, bool late, char[] error, int maxlen) { CreateNative("TF2Util_GetWeaponID", Native_GetWeaponID); CreateNative("TF2Util_GetWeaponMaxClip", Native_GetWeaponMaxClip); + CreateNative("TF2Util_GetPlayerShootPosition", Native_GetPlayerShootPosition); + return APLRes_Success; } @@ -78,6 +81,12 @@ public void OnPluginStart() { PrepSDKCall_AddParameter(SDKType_PlainOldData, SDKPass_Plain); g_SDKCallPlayerGetMaxAmmo = EndPrepSDKCall(); + StartPrepSDKCall(SDKCall_Player); + PrepSDKCall_SetFromConf(hGameConf, SDKConf_Virtual, + "CBaseCombatCharacter::Weapon_ShootPosition()"); + PrepSDKCall_SetReturnInfo(SDKType_Vector, SDKPass_ByValue); + g_SDKCallPlayerGetShootPosition = EndPrepSDKCall(); + StartPrepSDKCall(SDKCall_Raw); PrepSDKCall_SetReturnInfo(SDKType_PlainOldData, SDKPass_Plain); PrepSDKCall_SetFromConf(hGameConf, SDKConf_Signature, @@ -228,6 +237,17 @@ public int Native_GetPlayerWearableCount(Handle plugin, int nParams) { return GetEntData(client, view_as(offs_CTFPlayer_hMyWearables) + 0x0C); } +// void(int client, float result[3]); +public int Native_GetPlayerShootPosition(Handle plugin, int nParams) { + int client = GetNativeCell(1); + if (client < 1 || client > MaxClients || !IsClientInGame(client)) { + ThrowNativeError(SP_ERROR_NATIVE, "Client index %d is invalid", client); + } + float vecResult[3]; + SDKCall(g_SDKCallPlayerGetShootPosition, client, vecResult); + SetNativeArray(2, vecResult, sizeof(vecResult)); +} + // bool(int entity); public int Native_IsEntityWeapon(Handle plugin, int nParams) { int entity = GetNativeCell(1);