|
|
// ==================================================================
// CS2 骨骼索引 - 可用(截至 2026 年)
// 经测试,在 animgraph_2_beta 更新后可用。
// ==================================================================
enum BoneIndices : int {
ORIGIN = 0,
PELVIS = 1,
SPINE0 = 2,
SPINE1 = 3,
SPINE2 = 4,
NECK = 6,
HEAD = 7,
CLAVICLE_L = 8,
SHOULDER_L = 9,
ELBOW_L = 10,
HAND_L = 11,
CLAVICLE_R = 12,
SHOULDER_R = 13,
ELBOW_R = 14,
HAND_R = 15,
HIP_L = 17,
KNEE_L = 18,
FOOT_HEEL_L = 19,
HIP_R = 20,
KNEE_R = 21,
FOOT_HEEL_R = 22,
CHEST = 23,
GUN = 24,
EYE_L = 25,
EYE_R = 26,
RANDOM = 27,
CVJ_BONE = 28,
FOOT_TOES_L_T = 74,
FOOT_TOES_R_T = 77,
FOOT_TOES_L_CT = 81,
FOOT_TOES_R_CT = 86,
BONE_MAX = 128
};
// ====================================================================
// 骨骼连接
// ================================================================
struct bone_link { int a, b; };
static bone_link skeleton_links[] = {
// 脊柱
{ 骨盆, 脊柱1 },
{ 脊柱1, 脊柱2 },
{ 脊柱2, 胸部 },
{ 胸部, 颈部 },
{ 颈部, 头部 },
// 左臂
{ 颈部, 左锁骨 },
{ 左锁骨, 左肩 },
{ 左肩, 左肘 },
{ 左肘, 左手 },
// 右臂
{ 颈部, 右锁骨 },
{ 右锁骨, 右肩 },
{ 右肩, 右肘 },
{ 右肘, 右手 },
// 左腿
{ 骨盆, 左髋 },
{ 左髋, 左膝 },
{ 左膝, 左脚跟 },
// 右腿
{ PELVIS, HIP_R },
{ HIP_R, KNEE_R },
{ KNEE_R, FOOT_HEEL_R },
};
// ==================================================================
// 重要偏移量
// =================================================================
// 在您的 offsets.hpp 或任何您保存偏移量的地方:
namespace offsets {
namespace pawn {
constexpr std: trdiff_t m_pGameSceneNode = 0x330; // C_BaseEntity -> CGameSceneNode*
}
namespace bone {
constexpr std: trdiff_t m_modelState = 0x140; // CSkeletonInstance -> CModelState
}
}
// ==================================================================
// 获取骨骼数组 - 工作偏移量
// ===================================================================
uintptr_t GetBoneArray(uintptr_t pawn) {
if (!pawn) return 0;
uintptr_t gameScene = g_Memory->Read<uintptr_t>(pawn + offsets: awn::m_pGameSceneNode);
if (!gameScene) return 0;
// 工作偏移量:m_modelState (0x140) + 0x80 = 0x1C0
// 骨骼数组位于 gameScene + 0x1C0
uintptr_t boneArray = g_Memory->Read<uintptr_t>(gameScene + 0x1C0);
if (!boneArray) return 0;
// 通过检查头部位置验证骨骼
Vector3 testHead = g_Memory->Read<Vector3>(boneArray + HEAD * 32);
if (testHead.x == 0 && testHead.y == 0 && testHead.z == 0) return 0;
if (!std::isfinite(testHead.x)) return 0;
if (std::abs(testHead.x) > 65536.f) return 0;
return boneArray;
}
// ===================================================================
// 用法示例
// ===============================================================
void DrawSkeleton(uintptr_t pawn, ImDrawList* dl) {
uintptr_t boneArray = GetBoneArray(pawn);
if (!boneArray) return;
Vector3 bonePositions[BONE_MAX];
// 读取所有骨骼(步长 = 32 字节)
for (int i = 0; i < BONE_MAX; i++) {
bonePositions[i] = g_Memory->Read<Vector3>(boneArray + i * 32);
}
// 绘制骨架
for (const auto& link : skeleton_links) {
if (link.a >= BONE_MAX || link.b >= BONE_MAX) continue;
Vector3 worldPos1 = bonePositions[link.a];
Vector3 worldPos2 = bonePositions[link.b];
if (!IsValidBone(worldPos1) || !IsValidBone(worldPos2)) continue;
Vector2 screen1, screen2;
if (!WorldToScreen(worldPos1, screen1)) continue;
if (!WorldToScreen(worldPos2, screen2)) continue;
dl->AddLine(screen1, screen2, IM_COL32(255, 255, 255, 255), 1.5f);
}
}
|
-
|