#define W2S(w, s) UGameplayStatics::ProjectWorldToScreen(localController, w, true, s) // 辅助函数:检查是否应该跳过该玩家 bool ShouldSkipPlayer(ASTExtraPlayerCharacter* Player, ASTExtraPlayerController* localController, ASTExtraPlayerCharacter* localPlayer) { float Distance = localPlayer->GetDistanceTo(Player) / 100.0f; // 跳过条件 if (Distance > 600.0f) return true; if (Player->PlayerKey == localController->PlayerKey) return true; if (Player->bDead) return true; if (Config.PlayerESP.NoBot && Player->bIsAI) return true; return false; } // 辅助函数:绘制iOS风格预警指示器 void DrawAlertIndicator(ImDrawList* draw, ASTExtraPlayerCharacter* Player, ASTExtraPlayerCharacter* localPlayer, ASTExtraPlayerController* localController, ImColor borderColor, ImColor fillColor, int screenWidth, int screenHeight) { FVector MyPosition, EnemyPosition; // 获取位置 ASTExtraVehicleBase* CurrentVehiclea = Player->CurrentVehicle; if (CurrentVehiclea) { MyPosition = CurrentVehiclea->RootComponent->RelativeLocation; } else { MyPosition = Player->RootComponent->RelativeLocation; } ASTExtraVehicleBase* CurrentVehicle = localPlayer->CurrentVehicle; if (CurrentVehicle) { EnemyPosition = CurrentVehicle->RootComponent->RelativeLocation; } else { EnemyPosition = localPlayer->RootComponent->RelativeLocation; } // 计算雷达位置 bool shit = false; FVector EntityPos = WorldToRadar(localController->PlayerCameraManager->CameraCache.POV.Rotation.Yaw, MyPosition, EnemyPosition, NULL, NULL, Vector3(screenWidth, screenHeight, 0), shit); // 计算角度 FVector angle = FVector(); Vector3 forward = Vector3((float)(screenWidth / 2) - EntityPos.X, (float)(screenHeight / 2) - EntityPos.Y, 0.0f); VectorAnglesRadar(forward, angle); // 绘制iOS风格三角形指示器 const auto angle_yaw_rad = DEG2RAD(angle.Y + 180.f); const auto new_point_x = (screenWidth / 2) + 55 * 4 * cosf(angle_yaw_rad); const auto new_point_y = (screenHeight / 2) + 55 * 4 * sinf(angle_yaw_rad); std::array points { Vector3(new_point_x - 12, new_point_y - 12, 0.f), Vector3(new_point_x + 12, new_point_y, 0.f), Vector3(new_point_x - 12, new_point_y + 12, 0.f) }; RotateTriangle(points, angle.Y + 180.f); // iOS风格渐变填充 draw->AddTriangleFilled(ImVec2(points.at(0).X, points.at(0).Y), ImVec2(points.at(1).X, points.at(1).Y), ImVec2(points.at(2).X, points.at(2).Y), fillColor); // 细边框 draw->AddTriangle(ImVec2(points.at(0).X, points.at(0).Y), ImVec2(points.at(1).X, points.at(1).Y), ImVec2(points.at(2).X, points.at(2).Y), borderColor, 1.0f); } // 辅助函数:绘制iOS风格玩家方框 void DrawPlayerBox(ImDrawList* draw, ImVec2 headPos, ImVec2 rootPos, ImColor color, bool isMonster = false) { if (isMonster) { // 怪物方框:更大,填满怪物 float boxHeight = abs(headPos.y - rootPos.y) * 1.5f; // 怪物更高 float boxWidth = boxHeight * 0.8f; // 怪物更宽 // 调整怪物方框位置,确保居中 float centerY = headPos.y - (headPos.y - rootPos.y) / 2.0f; ImVec2 boxTop = ImVec2(headPos.x - (boxWidth / 2), centerY - boxHeight / 2); ImVec2 boxBottom = ImVec2(headPos.x + (boxWidth / 2), centerY + boxHeight / 2); // 怪物使用更醒目的方框 draw->AddRectFilled(boxTop, boxBottom, IM_COL32((int)(color.Value.x * 255), (int)(color.Value.y * 255), (int)(color.Value.z * 255), 30), 4.0f); draw->AddRect(boxTop, boxBottom, color, 4.0f, ImDrawFlags_RoundCornersAll, 2.5f); } else { // 玩家方框:iOS风格 float boxHeight = abs(headPos.y - rootPos.y); float boxWidth = boxHeight * 0.6f; ImVec2 boxTop = ImVec2(headPos.x - (boxWidth / 2), headPos.y); ImVec2 boxBottom = ImVec2(headPos.x + (boxWidth / 2), rootPos.y); // iOS风格半透明填充 draw->AddRectFilled(boxTop, boxBottom, IM_COL32((int)(color.Value.x * 255), (int)(color.Value.y * 255), (int)(color.Value.z * 255), 20), 4.0f); // iOS风格细边框 draw->AddRect(boxTop, boxBottom, color, 4.0f, ImDrawFlags_RoundCornersAll, 1.5f); } } // 辅助函数:绘制iOS风格血量条 void DrawHealthBar(ImDrawList* draw, ASTExtraPlayerCharacter* Player, ImVec2 headPosSC, ASTExtraPlayerController* localController, FVector HeadPos, bool isMonster = false) { float PercentHP = (Player->Health / Player->HealthMax) * 100; // 调整血条大小 float barWidth, barHeight, barX, barY; if (isMonster) { // 怪物血条:更大 barWidth = 80.0f; barHeight = 8.0f; } else { // 玩家血条 barWidth = 60.0f; barHeight = 6.0f; } barX = headPosSC.x - barWidth / 2; barY = headPosSC.y - 25.0f; // 调整位置,为玩家信息留出空间 // iOS风格毛玻璃背景 draw->AddRectFilled(ImVec2(barX, barY), ImVec2(barX + barWidth, barY + barHeight), ImColor(40, 40, 40, 200), barHeight / 2); // 计算血量颜色 ImColor healthColor; if (!localController->LineOfSightTo(localController->PlayerCameraManager, HeadPos, true)) { healthColor = ImColor(0, 122, 255, 220); // iOS蓝色 } else { // 根据血量渐变 if (PercentHP > 70) healthColor = ImColor(52, 199, 89, 220); // iOS绿色 else if (PercentHP > 30) healthColor = ImColor(255, 149, 0, 220); // iOS橙色 else healthColor = ImColor(255, 59, 48, 220); // iOS红色 } // 血量填充 float fillWidth = (barWidth * PercentHP) / 100.0f; if (fillWidth > 0) { draw->AddRectFilled(ImVec2(barX, barY), ImVec2(barX + fillWidth, barY + barHeight), healthColor, barHeight / 2); } // 细边框 draw->AddRect(ImVec2(barX, barY), ImVec2(barX + barWidth, barY + barHeight), ImColor(255, 255, 255, 80), barHeight / 2, 0, 0.8f); } // 辅助函数:绘制iOS风格玩家信息 void DrawPlayerInfo(ImDrawList* draw, ASTExtraPlayerCharacter* Player, ImVec2 headPosSC, ImVec2 rootPosSC, float Distance, bool isMonster = false) { // iOS风格字体和颜色 ImColor textColor = ImColor(255, 255, 255, 240); ImColor shadowColor = ImColor(0, 0, 0, 180); float fontSize = isMonster ? 18.0f : 16.0f; // 1. 显示玩家指针(调试用) if (世界) { auto MySelf = getPointer(getPointer(UE4 + 0x4634ef0) + 0x0) + 0x20; char extra[50]; sprintf(extra, "%p", MySelf); 绘制加粗文本(22, headPosSC.x, headPosSC.y + 10, textColor, shadowColor, extra); } // 2. 显示玩家名称和类型(带背景) if (Config.PlayerESP.名字) { std::string info; if (isMonster) { info = "年兽"; } else if (Player->bIsAI) { info = "AI"; } else { info = "玩家"; } // 添加队伍ID info = std::to_string((int)Player->TeamID) + " · " + info; auto textSize = ImGui::CalcTextSize(info.c_str()); // iOS风格文本背景 float padding = 6.0f; ImVec2 textPos = ImVec2(headPosSC.x - (textSize.x / 2.0f), headPosSC.y - 35.0f); ImVec2 bgMin = ImVec2(textPos.x - padding, textPos.y - padding/2); ImVec2 bgMax = ImVec2(textPos.x + textSize.x + padding, textPos.y + textSize.y + padding/2); draw->AddRectFilled(bgMin, bgMax, ImColor(0, 0, 0, 160), 6.0f); // 绘制文本 绘制加粗文本(fontSize, textPos.x, textPos.y, textColor, shadowColor, info.c_str()); } // 3. 显示距离(带背景) if (Config.PlayerESP.距离) { std::string distanceStr = std::to_string((int)Distance) + "M"; auto textSize = ImGui::CalcTextSize(distanceStr.c_str()); // iOS风格文本背景 float padding = 4.0f; ImVec2 textPos = ImVec2(rootPosSC.x - (textSize.x / 2.0f), rootPosSC.y + 5.0f); ImVec2 bgMin = ImVec2(textPos.x - padding, textPos.y - padding/2); ImVec2 bgMax = ImVec2(textPos.x + textSize.x + padding, textPos.y + textSize.y + padding/2); draw->AddRectFilled(bgMin, bgMax, ImColor(0, 0, 0, 160), 4.0f); // 绘制文本 ImColor distanceColor = isMonster ? ImColor(255, 149, 0, 240) : ImColor(0, 122, 255, 240); 绘制加粗文本(fontSize-2, textPos.x, textPos.y, distanceColor, shadowColor, distanceStr.c_str()); } } // 辅助函数:绘制玩家ESP(修复怪物绘制问题) void DrawPlayerESP(ImDrawList* draw, ASTExtraPlayerCharacter* Player, ASTExtraPlayerCharacter* localPlayer, ASTExtraPlayerController* localController, int screenWidth, int screenHeight) { float Distance = localPlayer->GetDistanceTo(Player) / 100.0f; // 特殊处理怪物(年兽) bool isMonster = (Player->bIsAI && (Player->GetName().find("Monster") != std::string::npos || Player->GetName().find("Beast") != std::string::npos || Player->GetName().find("年兽") != std::string::npos)); // 1. 获取位置 FVector HeadPos, RootPos; if (isMonster) { // 对于怪物,使用更准确的位置计算 HeadPos = Player->K2_GetActorLocation(); HeadPos.Z += 180.0f; // 怪物高度调整 RootPos = Player->K2_GetActorLocation(); RootPos.Z -= 60.0f; // 怪物底部调整 } else { // 正常玩家/人机 HeadPos = Player->GetBonePos("Head"); RootPos = Player->GetBonePos("Root"); } ImVec2 headPosSC, RootPosSC; // 检查位置是否可见 bool positionsVisible = W2S(HeadPos, (FVector2D*)&headPosSC) && W2S(RootPos, (FVector2D*)&RootPosSC); if (!positionsVisible) { // 如果不可见,尝试使用更简单的方法 FVector actorPos = Player->K2_GetActorLocation(); if (!W2S(actorPos, (FVector2D*)&headPosSC)) { return; } if (isMonster) { // 怪物:创建合适的方框高度 RootPosSC = ImVec2(headPosSC.x, headPosSC.y + 100.0f); } else { RootPosSC = ImVec2(headPosSC.x, headPosSC.y + 50.0f); } } // 调整怪物位置:确保方框正确居中 if (isMonster) { // 调整头部位置,使方框更准确 float boxHeight = abs(headPosSC.y - RootPosSC.y); headPosSC.y = headPosSC.y - boxHeight * 0.2f; // 向上调整 } // 2. 确定颜色 bool IsVisible = localController->LineOfSightTo(Player, {0, 0, 0}, true); ImColor PlayerBoxClrCf, PlayerBoxClrCf2, SkeletonColor; if (isMonster) { // 怪物使用特殊颜色 PlayerBoxClrCf = ImColor(255, 149, 0, 255); // iOS橙色 PlayerBoxClrCf2 = ImColor(255, 149, 0, 80); SkeletonColor = ImColor(255, 149, 0, 200); } else if (IsVisible) { if (Player->bIsAI) { PlayerBoxClrCf = ImColor(52, 199, 89, 255); // iOS绿色 SkeletonColor = ImColor(52, 199, 89, 200); } else { PlayerBoxClrCf = ImColor(255, 59, 48, 255); // iOS红色 SkeletonColor = ImColor(255, 59, 48, 200); } PlayerBoxClrCf2 = ImColor(IM_COL32((int)(PlayerBoxClrCf.Value.x * 255), (int)(PlayerBoxClrCf.Value.y * 255), (int)(PlayerBoxClrCf.Value.z * 255), 80)); } else { PlayerBoxClrCf = ImColor(142, 142, 147, 255); // iOS灰色 PlayerBoxClrCf2 = ImColor(142, 142, 147, 80); SkeletonColor = ImColor(142, 142, 147, 200); } // 3. 绘制各种ESP元素 // 3.1 预警指示器 if (Config.PlayerESP.Alert) { DrawAlertIndicator(draw, Player, localPlayer, localController, PlayerBoxClrCf, PlayerBoxClrCf2, screenWidth, screenHeight); } // 3.2 连线 if (Config.PlayerESP.Line) { draw->AddLine(ImVec2((float)screenWidth / 2, (float)screenHeight / 8), ImVec2(headPosSC.x, headPosSC.y - 15.0f), PlayerBoxClrCf, 1.5f); } // 3.3 方框 if (Config.PlayerESP.Box) { DrawPlayerBox(draw, headPosSC, RootPosSC, PlayerBoxClrCf, isMonster); } // 3.4 骨骼(仅对非怪物绘制) if (Config.PlayerESP.Skeleton && !isMonster) { // 获取其他骨骼位置 ImVec2 upper_rPoSC, lowerarm_rPoSC, hand_rPoSC; ImVec2 upper_lPoSC, lowerarm_lSC, hand_lPoSC; ImVec2 thigh_lPoSC, calf_lPoSC, foot_lPoSC; ImVec2 thigh_rPoSC, calf_rPoSC, foot_rPoSC; ImVec2 neck_01PoSC, pelvisPoSC; // 检查骨骼是否可见 FVector bonePositions[] = { Player->GetBonePos("upperarm_r"), Player->GetBonePos("lowerarm_r"), Player->GetBonePos("hand_r"), Player->GetBonePos("upperarm_l"), Player->GetBonePos("lowerarm_l"), Player->GetBonePos("hand_l"), Player->GetBonePos("thigh_l"), Player->GetBonePos("calf_l"), Player->GetBonePos("foot_l"), Player->GetBonePos("thigh_r"), Player->GetBonePos("calf_r"), Player->GetBonePos("foot_r"), Player->GetBonePos("neck_01"), Player->GetBonePos("pelvis") }; if (W2S(bonePositions[0], (FVector2D*)&upper_rPoSC) && W2S(bonePositions[1], (FVector2D*)&lowerarm_rPoSC) && W2S(bonePositions[2], (FVector2D*)&hand_rPoSC) && W2S(bonePositions[3], (FVector2D*)&upper_lPoSC) && W2S(bonePositions[4], (FVector2D*)&lowerarm_lSC) && W2S(bonePositions[5], (FVector2D*)&hand_lPoSC) && W2S(bonePositions[6], (FVector2D*)&thigh_lPoSC) && W2S(bonePositions[7], (FVector2D*)&calf_lPoSC) && W2S(bonePositions[8], (FVector2D*)&foot_lPoSC) && W2S(bonePositions[9], (FVector2D*)&thigh_rPoSC) && W2S(bonePositions[10], (FVector2D*)&calf_rPoSC) && W2S(bonePositions[11], (FVector2D*)&foot_rPoSC) && W2S(bonePositions[12], (FVector2D*)&neck_01PoSC) && W2S(bonePositions[13], (FVector2D*)&pelvisPoSC)) { // 绘制骨骼连线 draw->AddLine(upper_rPoSC, neck_01PoSC, SkeletonColor, 1.8f); draw->AddLine(upper_lPoSC, neck_01PoSC, SkeletonColor, 1.8f); draw->AddLine(upper_rPoSC, lowerarm_rPoSC, SkeletonColor, 1.8f); draw->AddLine(lowerarm_rPoSC, hand_rPoSC, SkeletonColor, 1.8f); draw->AddLine(upper_lPoSC, lowerarm_lSC, SkeletonColor, 1.8f); draw->AddLine(lowerarm_lSC, hand_lPoSC, SkeletonColor, 1.8f); draw->AddLine(thigh_rPoSC, thigh_lPoSC, SkeletonColor, 1.8f); draw->AddLine(thigh_lPoSC, calf_lPoSC, SkeletonColor, 1.8f); draw->AddLine(calf_lPoSC, foot_lPoSC, SkeletonColor, 1.8f); draw->AddLine(thigh_rPoSC, calf_rPoSC, SkeletonColor, 1.8f); draw->AddLine(calf_rPoSC, foot_rPoSC, SkeletonColor, 1.8f); draw->AddLine(neck_01PoSC, pelvisPoSC, SkeletonColor, 1.8f); draw->AddLine(neck_01PoSC, headPosSC, SkeletonColor, 1.8f); } } // 3.5 血量条 if (Config.PlayerESP.血量) { DrawHealthBar(draw, Player, headPosSC, localController, HeadPos, isMonster); } // 3.6 玩家信息 DrawPlayerInfo(draw, Player, headPosSC, RootPosSC, Distance, isMonster); } // 武器相关辅助函数 void ApplyWeaponDamageMultiplier(ASTExtraPlayerCharacter* localPlayer) { auto WeaponManagerComponent = localPlayer->WeaponManagerComponent; if (!WeaponManagerComponent) return; auto propSlot = WeaponManagerComponent->GetCurrentUsingPropSlot(); if ((int)propSlot.GetValue() < 1 || (int)propSlot.GetValue() > 3) return; auto CurrentWeaponReplicated = (ASTExtraShootWeapon*)WeaponManagerComponent->CurrentWeaponReplicated; if (!CurrentWeaponReplicated) return; auto ShootWeaponComponent = CurrentWeaponReplicated->ShootWeaponComponent; if (!ShootWeaponComponent) return; UShootWeaponEntity* ShootWeaponEntityComponent = ShootWeaponComponent->ShootWeaponEntityComponent; if (!ShootWeaponEntityComponent) return; ShootWeaponEntityComponent->BulletNumSingleShot = 50; } void ApplyWeaponRecoilControl(ASTExtraPlayerCharacter* localPlayer) { auto WeaponManagerComponent = localPlayer->WeaponManagerComponent; if (!WeaponManagerComponent) return; auto Slot = WeaponManagerComponent->GetCurrentUsingPropSlot(); if ((int)Slot.GetValue() < 1 || (int)Slot.GetValue() > 3) return; auto CurrentWeaponReplicated = (ASTExtraShootWeapon*)WeaponManagerComponent->CurrentWeaponReplicated; if (!CurrentWeaponReplicated) return; auto ShootWeaponEntityComp = CurrentWeaponReplicated->ShootWeaponEntityComp; auto ShootWeaponEffectComp = CurrentWeaponReplicated->ShootWeaponEffectComp; if (!ShootWeaponEntityComp || !ShootWeaponEffectComp) return; // 重置后坐力 memset(&ShootWeaponEntityComp->RecoilInfo, 0, sizeof(FSRecoilInfo)); ShootWeaponEntityComp->AccessoriesVRecoilFactor = 0.0f; ShootWeaponEntityComp->AccessoriesHRecoilFactor = 0.0f; ShootWeaponEntityComp->AccessoriesRecoveryFactor = 0.0f; // 重置偏差 memset(&ShootWeaponEntityComp->DeviationInfo, 0, sizeof(FSDeviation)); ShootWeaponEntityComp->ShotGunVerticalSpread = 0.0f; ShootWeaponEntityComp->ShotGunHorizontalSpread = 0.0f; ShootWeaponEntityComp->GameDeviationFactor = 0.0f; ShootWeaponEntityComp->GameDeviationAccuracy = 0.0f; // 重置准星 ShootWeaponEntityComp->CrossHairInitialSize = 0.0f; ShootWeaponEntityComp->CrossHairBurstSpeed = 0.0f; ShootWeaponEntityComp->CrossHairBurstIncreaseSpeed = 0.0f; ShootWeaponEntityComp->RecoilKickADS = 0.0f; // 重置相机抖动 ShootWeaponEffectComp->CameraShakeInnerRadius = 0.0f; ShootWeaponEffectComp->CameraShakeOuterRadius = 0.0f; ShootWeaponEffectComp->CameraShakFalloff = 0.0f; } void ApplyWeaponScale(ASTExtraPlayerCharacter* localPlayer) { auto WeaponManagerComponent = localPlayer->WeaponManagerComponent; if (!WeaponManagerComponent) return; auto Slot = WeaponManagerComponent->GetCurrentUsingPropSlot(); if ((int)Slot.GetValue() < 1 || (int)Slot.GetValue() > 3) return; auto CurrentWeaponReplicated = (ASTExtraShootWeapon*)WeaponManagerComponent->CurrentWeaponReplicated; if (!CurrentWeaponReplicated) return; CurrentWeaponReplicated->RootComponent->RelativeScale3D.Y = Gun_Size; CurrentWeaponReplicated->RootComponent->RelativeScale3D.Z = Gun_Size; CurrentWeaponReplicated->RootComponent->RelativeScale3D.X = Gun_Size; } void ApplyWeaponDamage(ASTExtraPlayerCharacter* localPlayer) { auto WeaponManagerComponent = localPlayer->WeaponManagerComponent; if (!WeaponManagerComponent) return; auto Slot = WeaponManagerComponent->GetCurrentUsingPropSlot(); if ((int)Slot.GetValue() < 1 || (int)Slot.GetValue() > 3) return; auto CurrentWeaponReplicated = (ASTExtraShootWeapon*)WeaponManagerComponent->CurrentWeaponReplicated; if (!CurrentWeaponReplicated) return; auto ShootWeaponEntityComp = CurrentWeaponReplicated->ShootWeaponEntityComp; if (!ShootWeaponEntityComp) return; ShootWeaponEntityComp->BaseImpactDamage = 伤害值 * 伤害倍率; } // 辅助函数:应用玩家功能 void ApplyPlayerFeatures(ASTExtraPlayerCharacter* localPlayer, ASTExtraPlayerController* localController, int screenWidth, int screenHeight) { // 1. 高跳功能 if (高跳) { UCharacterMovementComponent* CharacterMovement = localPlayer->CharacterMovement; if (CharacterMovement) { CharacterMovement->JumpZVelocity = 高度; CharacterMovement->GravityScale = 2.0f; CharacterMovement->MaxStepHeight = 999.9f; } } // 2. 人物旋转功能 if (chongchongche) { USceneComponent* MeshContainer = g_LocalPlayer->MeshContainer; MeshContainer->RelativeRotation = {0, chongchongche1, 0}; chongchongche1 += chongchongche2; if (chongchongche1 >= tocdoquay) chongchongche1 = 0.0f; chongchongche1 += 50; } // 3. 人物缩放功能 if (人物变大) { USceneComponent* MeshContainer = g_LocalPlayer->MeshContainer; MeshContainer->SetWorldScale3D({巨人, 巨人, 巨人}); } // 4. 飞天功能 if (飞天跳开) { localPlayer->CharacterMovement->MaxAcceleration = 9999999.0f; localPlayer->CustomTimeDilation = 0.7f; localPlayer->EnergySpeedScale = 6.0f; localPlayer->CharacterMovement->JumpZVelocity = 2200.0f; localPlayer->CharacterMovement->bMaintainHorizontalGroundVelocity = true; } if (飞天跳关) { localPlayer->CharacterMovement->MaxAcceleration = 10000.828f; localPlayer->CustomTimeDilation = 1.0f; localPlayer->EnergySpeedScale = 1.0f; localPlayer->CharacterMovement->bMaintainHorizontalGroundVelocity = false; localPlayer->CharacterMovement->JumpZVelocity = 500.0f; } // 5. 能量加速功能 if (能量加速开) { auto GWorld = GetWorld(); if (localPlayer->Energy.EnergyCurrent >= 65) { GWorld->PersistentLevel->WorldSettings->MinUndilatedFrameTime = 0.210f; } } if (能量加速关) { auto GWorld = GetWorld(); if (localPlayer->Energy.EnergyCurrent >= 65) { GWorld->PersistentLevel->WorldSettings->MinUndilatedFrameTime = 0.000f; } } // 6. 武器功能 if (伤害测试2) { ApplyWeaponDamageMultiplier(localPlayer); } if (枪械一套) { ApplyWeaponRecoilControl(localPlayer); } if (枪械变大) { ApplyWeaponScale(localPlayer); } if (广角) { localPlayer->ThirdPersonCameraComponent->SetFieldOfView(视角); } if (开启伤害) { ApplyWeaponDamage(localPlayer); } // 7. 飞行功能 if (飞天2) { UCharacterMovementComponent* CharacterMovement = localPlayer->CharacterMovement; if (CharacterMovement) { CharacterMovement->SetMovementMode(EMovementMode::MOVE_Flying, 1); FVector NewLocation = localPlayer->K2_GetActorLocation(); NewLocation.Z += 10.0f; CharacterMovement->GravityScale = 0.0f; localPlayer->K2_SetActorLocation(NewLocation, 0, false, nullptr); } } if (飞天1) { UCharacterMovementComponent* CharacterMovement = localPlayer->CharacterMovement; if (CharacterMovement) { CharacterMovement->GravityScale = 0.f; } } if (飞天关) { UCharacterMovementComponent* CharacterMovement = g_LocalPlayer->CharacterMovement; CharacterMovement->SetMovementMode(EMovementMode::MOVE_Walking, 1); CharacterMovement->GravityScale = 1.0f; } // 8. 修复功能 if (修复着陆) { g_LocalPlayer->STPlayerController->bCanOpenParachute = true; g_LocalPlayer->STPlayerController->bCanCloseParachute = true; g_LocalPlayer->STPlayerController->bLandAfterJumpPlane = true; } } // 辅助函数:应用载具功能 void ApplyVehicleFeatures(ASTExtraPlayerCharacter* localPlayer, ASTExtraPlayerController* localController) { if (!自控初始化 || !localPlayer) return; auto CurrentVehicle2 = localPlayer->CurrentVehicle; if (!CurrentVehicle2) return; auto RootComponent = static_cast(CurrentVehicle2->K2_GetRootComponent()); if (!RootComponent) return; // 1. 旋转控制 if (转圈) { auto RootComponent2 = static_cast(CurrentVehicle2->K2_GetRootComponent()); RootComponent2->SetAllPhysicsAngularVelocity({0.f, 0.f, 26.5f}, true); } if (转圈2) { auto RootComponent2 = static_cast(CurrentVehicle2->K2_GetRootComponent()); RootComponent2->SetAllPhysicsAngularVelocity({0.f, 0.f, -26.5f}, true); } // 2. 碰撞控制 if (无视碰撞开) { CurrentVehicle2->SetActorEnableCollision(false); } else { CurrentVehicle2->SetActorEnableCollision(true); } // 3. 重力控制 if (无视重力开) { auto RootComponent3 = static_cast(CurrentVehicle2->K2_GetRootComponent()); RootComponent3->SetEnableGravity(false); } else { auto RootComponent3 = static_cast(CurrentVehicle2->K2_GetRootComponent()); RootComponent3->SetEnableGravity(true); } // 4. 载具速度控制 float coeff = (60.0f * 60.0f) * 10.f * 0.01 * 载具速度; float coefff = (60.0f * 60.0f) * 10.f * 0.01 * 喇叭高度; FVector vel = {0, 0, 0}; auto yaw = localController->PlayerCameraManager->CameraCache.POV.Rotation.Yaw; bool isMoving = false; // 5. 不同模式的移动控制 auto CurrentVehicle = localPlayer->GetCurrentVehicle(); // 老爷模式(喇叭控制) if (老爷模式 && CurrentVehicle->bIsUsingHorn) { isMoving = true; float theta = 2.f * M_PI * (yaw / 360.f); vel.X = (coeff * cosf(theta)); vel.Y = (coeff * sinf(theta)); auto RootComponent5 = static_cast(CurrentVehicle2->K2_GetRootComponent()); RootComponent5->SetAllPhysicsLinearVelocity(vel, false); } // 飞船模式(加速控制) if (飞船模式 && CurrentVehicle->bIsBoosting) { isMoving = true; float theta = 2.f * M_PI * (yaw / 360.f); vel.X = (coeff * cosf(theta)); vel.Y = (coeff * sinf(theta)); if (喇叭飞天) { vel.Z = (coefff * sinf(theta)); } auto RootComponent6 = static_cast(CurrentVehicle2->K2_GetRootComponent()); RootComponent6->SetAllPhysicsLinearVelocity(vel, false); } // 喇叭飞天模式 if (喇叭飞天 && CurrentVehicle->bIsUsingHorn) { isMoving = true; vel.Z = (coefff / 4); auto RootComponent7 = static_cast(CurrentVehicle2->K2_GetRootComponent()); RootComponent7->SetAllPhysicsLinearVelocity(vel, false); } // 载具加速模式 if (载具加速 && CurrentVehicle->bIsBoosting) { isMoving = true; float theta = 2.f * M_PI * (yaw / 360.f); vel.X = (coeff * cosf(theta)); vel.Y = (coeff * sinf(theta)); auto RootComponent8 = static_cast(CurrentVehicle2->K2_GetRootComponent()); RootComponent8->SetAllPhysicsLinearVelocity(vel, false); } // 6. 停止移动 if (!isMoving) { vel = {0, 0, 0}; RootComponent->SetAllPhysicsLinearVelocity(vel, true); } } void DrawESP(ImDrawList* draw, int screenWidth, int screenHeight) { if (Config.OTHER.HIDEESP) { HIDEESP = false; } else { HIDEESP = true; } if (!HIDEESP) { return; } auto Actors = getActors(); int totalEnemies = 0, totalBots = 0, totalMonsters = 0; ASTExtraPlayerCharacter* localPlayer = nullptr; ASTExtraPlayerController* localController = nullptr; // 1. 查找本地控制器 for (int i = 0; i < Actors.size(); i++) { auto Actor = Actors[i]; if (isObjectInvalid(Actor)) continue; if (Actor->IsA(ASTExtraPlayerController::StaticClass())) { localController = (ASTExtraPlayerController*)Actor; break; } } if (!localController) return; // 2. 查找本地玩家 for (int i = 0; i < Actors.size(); i++) { auto Actor = Actors[i]; if (isObjectInvalid(Actor)) continue; if (Actor->IsA(ASTExtraPlayerCharacter::StaticClass())) { if (((ASTExtraPlayerCharacter*)Actor)->PlayerKey == localController->PlayerKey) { localPlayer = (ASTExtraPlayerCharacter*)Actor; break; } } } if (!localPlayer) return; // 3. 处理所有Actor for (int i = 0; i < Actors.size(); i++) { auto Actor = Actors[i]; if (isObjectInvalid(Actor)) continue; // 3.1 处理玩家 if (Actor->IsA(ASTExtraPlayerCharacter::StaticClass())) { auto Player = (ASTExtraPlayerCharacter*)Actor; // 跳过条件检查 if (ShouldSkipPlayer(Player, localController, localPlayer)) { continue; } // 检查是否为怪物 bool isMonster = (Player->bIsAI && (Player->GetName().find("Monster") != std::string::npos || Player->GetName().find("Beast") != std::string::npos || Player->GetName().find("年兽") != std::string::npos)); // 更新计数 if (isMonster) { totalMonsters++; } else if (Player->bIsAI) { totalBots++; } else { totalEnemies++; } // 绘制玩家ESP DrawPlayerESP(draw, Player, localPlayer, localController, screenWidth, screenHeight); } // 3.2 处理战利品箱 if (Config.PlayerESP.LootBox && Actor->IsA(APickUpListWrapperActor::StaticClass())) { auto LootBox = (APickUpListWrapperActor*)Actor; auto RootComponent = Actor->RootComponent; if (!RootComponent) continue; float Distance = LootBox->GetDistanceTo(localPlayer) / 100.f; FVector2D lootboxPos; if (W2S(LootBox->K2_GetActorLocation(), &lootboxPos)) { std::string s = "物资箱 "; s += std::to_string((int)Distance); s += "m"; // 计算文本大小并绘制背景 auto textSize = ImGui::CalcTextSize(s.c_str()); float padding = 4.0f; ImVec2 bgMin = ImVec2(lootboxPos.X - padding, lootboxPos.Y - padding/2); ImVec2 bgMax = ImVec2(lootboxPos.X + textSize.x + padding, lootboxPos.Y + textSize.y + padding/2); draw->AddRectFilled(bgMin, bgMax, ImColor(0, 0, 0, 160), 4.0f); draw->AddText(NULL, 16.0f, ImVec2(lootboxPos.X, lootboxPos.Y), ImColor(255, 204, 0, 240), s.c_str()); } } // 3.3 处理游戏状态(剩余人数) if (Config.PlayerESP.剩余人数 && Actor->IsA(ASTExtraGameStateBase::StaticClass())) { auto InGame = (ASTExtraGameStateBase*)Actor; std::string s = "剩余: " + std::to_string((int)InGame->AlivePlayerNum); // 计算文本大小 auto textSize = ImGui::CalcTextSize(s.c_str()); float padding = 8.0f; // iOS风格背景 ImVec2 bgMin = ImVec2(screenWidth / 2.1f - textSize.x/2 - padding, 245); ImVec2 bgMax = ImVec2(screenWidth / 2.1f + textSize.x/2 + padding, 245 + textSize.y + padding); draw->AddRectFilled(bgMin, bgMax, ImColor(0, 0, 0, 180), 8.0f); draw->AddRect(bgMin, bgMax, ImColor(255, 255, 255, 80), 8.0f, 0, 1.0f); draw->AddText(nullptr, 20.0f, ImVec2(screenWidth / 2.1f - textSize.x/2, 250), ImColor(255, 255, 255, 240), s.c_str()); } } // 4. 全局状态显示 g_LocalController = localController; g_LocalPlayer = localPlayer; // 4.1 显示玩家/人机/怪物数量(iOS风格) if (人数) { // 背景 ImVec2 bgMin = ImVec2(screenWidth / 1.73f - 220, 35); ImVec2 bgMax = ImVec2(screenWidth / 1.73f, 85); draw->AddRectFilled(bgMin, bgMax, ImColor(0, 0, 0, 200), 10.0f); draw->AddRect(bgMin, bgMax, ImColor(255, 255, 255, 100), 10.0f, 0, 1.0f); // 文本 char infoText[256]; sprintf(infoText, "玩家: %d\n人机: %d\n怪物: %d", totalEnemies, totalBots, totalMonsters); draw->AddText(ImVec2(screenWidth / 1.73f - 210, 40), ImColor(255, 255, 255, 240), infoText); } // 4.2 应用玩家功能 ApplyPlayerFeatures(localPlayer, localController, screenWidth, screenHeight); // 4.3 应用载具功能 ApplyVehicleFeatures(localPlayer, localController); // 5. 绘制水印(保持原位置和内容) if (水印) { // 使用原水印内容和位置 std::string watermarkText = T("by.脑干\n当前内部测试版-不代表最终品质", "by.SuRanCi\nCurrent internal beta-does not represent final quality"); // 原位置:{screenWidth + 200, 650},但需要调整到可见位置 // 调整为右下角位置 ImVec2 watermarkPos = ImVec2(screenWidth - 350, screenHeight - 65); // 计算文本大小并绘制背景 auto textSize = ImGui::CalcTextSize(watermarkText.c_str()); float padding = 6.0f; ImVec2 bgMin = ImVec2(watermarkPos.x - padding, watermarkPos.y - padding); ImVec2 bgMax = ImVec2(watermarkPos.x + textSize.x + padding, watermarkPos.y + textSize.y + padding); // iOS风格背景 draw->AddRectFilled(bgMin, bgMax, ImColor(0, 0, 0, 180), 6.0f); draw->AddRect(bgMin, bgMax, ImColor(255, 255, 255, 80), 6.0f, 0, 1.0f); // 绘制文本 draw->AddText(watermarkPos, ImColor(255, 59, 48, 240), // iOS红色 watermarkText.c_str()); } }