Repository navigation
Expand file tree
/
Copy pathAimbotModule.cs
More file actions
173 lines (147 loc) · 7.78 KB
/
Copy pathAimbotModule.cs
File metadata and controls
173 lines (147 loc) · 7.78 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
using System.Collections.Generic;
using BepInEx.Configuration;
using HarmonyLib;
using UnityEngine;
namespace HTFToolkit
{
/// <summary>
/// 自瞄:Harmony 后缀挂在 PlayerCamera.Update。
/// 每帧在游戏自己应用完旋转后,把相机旋转量朝最近的可打击目标修正。
/// 目标筛选逻辑复刻游戏原生 PlayerAimAssist(活体 / 视锥角 / 遮挡检测),
/// 并优先瞄头部区域(利用 Creature.HeadPos 判定的头部位置)。
/// </summary>
internal static class AimbotModule
{
public static bool Enabled;
private static ConfigEntry<float> _maxDistance;
private static ConfigEntry<float> _maxAngle;
private static ConfigEntry<float> _aimSharpness;
private static ConfigEntry<float> _maxSpeed;
private static ConfigEntry<bool> _preferHead;
private static ConfigEntry<bool> _onlyWhileAds;
private static ConfigEntry<bool> _targetPlayers;
/// <summary>菜单开关用:当前是否锁定玩家(随 cfg 持久化)。</summary>
public static bool TargetPlayersOn => _targetPlayers != null && _targetPlayers.Value;
public static void ToggleTargetPlayers()
{
if (_targetPlayers == null)
return;
_targetPlayers.Value = !_targetPlayers.Value;
ToastModule.Show("自瞄锁定玩家(PVP)", _targetPlayers.Value);
Plugin.Log?.LogInfo($"Aimbot targetPlayers: {_targetPlayers.Value}");
}
private static readonly Dictionary<Transform, Item> _empty = new Dictionary<Transform, Item>();
public static void BindConfig(ConfigFile cfg)
{
_maxDistance = cfg.Bind("自瞄", "最大距离", 60f, "目标最大搜索距离");
_maxAngle = cfg.Bind("自瞄", "最大视锥角", 40f, "偏离准星多少度内的目标才会被锁定");
_aimSharpness = cfg.Bind("自瞄", "跟踪强度", 30f, "越大转向越快越硬(推荐 15~40;后坐力大时调高)");
_maxSpeed = cfg.Bind("自瞄", "最大角速度", 900f, "每秒最大修正角度上限(后坐力抖动大时调高)");
_preferHead = cfg.Bind("自瞄", "优先爆头", true, "瞄准生物头部区域以触发爆头倍率");
_onlyWhileAds = cfg.Bind("自瞄", "仅开镜生效", true, "默认开启:必须按住右键瞄准(ADS)时才追踪,松开立即停止;设为 false 则开启自瞄后一直追踪");
_targetPlayers = cfg.Bind("自瞄", "锁定玩家", true, "自瞄目标包含其他玩家(PVP 用;公共房请注意礼仪)");
}
public static void ApplyPatches(Harmony harmony)
{
harmony.Patch(
AccessTools.Method(typeof(PlayerCamera), "Update"),
postfix: new HarmonyMethod(AccessTools.Method(typeof(AimbotModule), nameof(Postfix))));
}
private static void Postfix(PlayerCamera __instance)
{
if (!Enabled || Time.timeScale <= 0f || !Compat.GameInfoReady)
return;
Player player = Traverse.Create(__instance).Field<Player>("_player").Value;
if (player == null || player.BlockInputs || !player.Camera.MouseLocked || GameInfo.Input == null)
return;
Item held = player.Holding.HeldItem;
bool holdingWeapon = held && held.Weapon;
if (_onlyWhileAds.Value && (!holdingWeapon || !held.Weapon.IsAds))
return;
Transform camT = __instance.CamTransform;
Vector3 camPos = camT.position;
Vector3 camFwd = camT.forward;
Transform target = FindBestTarget(camPos, camFwd, holdingWeapon, out Vector3 aimPoint);
if (target == null)
return;
Vector3 desiredDir = aimPoint - camPos;
if (desiredDir.sqrMagnitude < 0.0001f)
return;
Quaternion look = Quaternion.LookRotation(desiredDir.normalized, Vector3.up);
Vector3 desired = look.eulerAngles;
Vector3 cur = Traverse.Create(__instance).Field<Vector3>("_rot").Value;
float dx = Mathf.DeltaAngle(cur.x, desired.x);
float dy = Mathf.DeltaAngle(cur.y, desired.y);
float t = 1f - Mathf.Exp(-_aimSharpness.Value * Time.deltaTime);
float maxStep = _maxSpeed.Value * Time.deltaTime;
Vector2 delta = Vector2.ClampMagnitude(new Vector2(dx * t, dy * t), maxStep);
Traverse.Create(__instance).Field<Vector3>("_rot").Value =
cur + new Vector3(delta.x, delta.y, 0f);
}
private static Transform FindBestTarget(Vector3 camPos, Vector3 camFwd, bool holdingWeapon, out Vector3 aimPoint)
{
Transform best = null;
Vector3 bestAim = Vector3.zero;
float bestScore = float.MaxValue;
float maxSqr = _maxDistance.Value * _maxDistance.Value;
float minAlignment = Mathf.Cos(_maxAngle.Value * Mathf.Deg2Rad);
int obstructionMask = (int)GameInfo.LevelLayer | (int)GameInfo.BoatLayer;
void Evaluate(Transform anchor, Vector3 targetPos)
{
Vector3 toTarget = targetPos - camPos;
float sqrMag = toTarget.sqrMagnitude;
if (sqrMag < Mathf.Epsilon || sqrMag > maxSqr)
return;
float alignment = Vector3.Dot(camFwd, toTarget) / Mathf.Sqrt(sqrMag);
if (alignment < minAlignment)
return;
if (Physics.Linecast(camPos, targetPos, obstructionMask, QueryTriggerInteraction.Ignore))
return;
// 评分:越靠近准星越优先,其次距离
float score = (1f - alignment) / Mathf.Max(1f - minAlignment, Mathf.Epsilon)
+ sqrMag / maxSqr * 0.1f;
if (score < bestScore)
{
bestScore = score;
best = anchor;
bestAim = targetPos;
}
}
// ---- 生物(ItemManager 里的 Creature)----
foreach (KeyValuePair<Transform, Item> kv in ItemManager.Items)
{
Item item = kv.Value;
// Creature 继承 Item,优先类型判断;再兼容物品上挂的关联生物(item.Creature)
Creature creature = item as Creature;
if (creature == null && item != null)
creature = item.Creature;
if (!Compat.CreatureAlive(creature)) // v1.8.6:读 SyncVar 本体,修复联机客户端 IsDead 误判
continue;
Vector3 targetPos = creature.Rig ? creature.Rig.worldCenterOfMass : creature.transform.position;
Evaluate(creature.transform, targetPos);
}
// ---- 其他玩家(v1.9.13:自瞄锁定玩家,PVP)----
if (_targetPlayers != null && _targetPlayers.Value && PlayerManager.OtherPlayers != null)
{
foreach (Player p in PlayerManager.OtherPlayers)
{
if (p == null || p == Player.LocalPlayer)
continue;
try
{
if (p.Dying != null && p.Dying.IsDead)
continue;
}
catch
{
// Dying 未初始化,按存活处理
}
Vector3 pos = p.Rigidbody ? p.Rigidbody.worldCenterOfMass : p.transform.position;
Evaluate(p.transform, pos + Vector3.up * 0.5f); // 瞄胸口
}
}
aimPoint = best != null ? bestAim : Vector3.zero;
return best;
}
}
}