Manico CSGOBetterbots指南:深入解析
bot_stuff.sp篇
© 2025 All rights reserved.
恭喜你找到了这个宝藏!本指南将带你了解Manico的Betterbots插件。主要围绕bot_stuff.sp这个关键的模块。这里假定被我命名为 bot_stuff_manico_20250813.sp。通过本指南,你可以理解其工作原理,并学会如何自定义这些强大的功能。
2. SourceMod 是什么?
在深入学习插件之前,我们先来简单了解一下 SourceMod。
- 概念: SourceMod (简称 SM) 是一个针对 Valve Source 引擎游戏 (如 CS:GO, CS:S, TF2 等) 的服务器管理和插件框架。它允许服务器管理员通过编写脚本或安装插件来修改、增强游戏体验,添加新功能,甚至创造全新的游戏模式。
- 为什么重要: 所有的 SourceMod 插件都依赖这个框架运行。它提供了与游戏内部机制交互的接口,让开发者能够读取、修改游戏数据,执行命令,响应游戏事件等。
-
本插件与 SourceMod 的关系:
.sp文件就是 SourceMod 插件的源代码文件。它需要编译成.smx文件才能被 SourceMod 加载和运行。本插件通过 SourceMod 提供的功能,深入修改了 CS:GO 内部的机器人行为逻辑。
3. 核心功能解析
这个插件做了很多“不简单”的事情,让我们来一一揭秘。
3.1. 专业级 Bot AI:模拟职业选手行为
插件最引人注目的功能是让机器人模仿职业选手。它通过调整 Bot 的内部参数和决策逻辑来实现:
-
职业选手档案(
bot_info.json): 插件内置了一些职业选手的名字(如 s1mple, ZywOo, NiKo 等)。如果 Bot 的名字匹配,它将获得特殊的增强。 -
反应时间与攻击性: 模拟职业选手的超快反应速度(
g_fReactionTime接近0)和激进的攻击性(g_fAggression接近1)。普通 Bot 也将获得随机但提升的反应速度和攻击性。 -
视野调整(
g_fLookAngleMaxAccel): 调整 Bot 视野移动的最大加速度,使其瞄准更迅速、更流畅,如同人类玩家。 -
动态准星(
g_szCrosshairCode): 插件能为 Bot 设置特定的准星代码,这些代码可以是从职业选手配置中获取的。让 Bot 不仅行为像,连“看”起来都像。 -
智能瞄准(
SelectBestTargetPos): Bot 不再盲目瞄准身体,它会尝试优先爆头(head_0骨骼),如果头部不可见,则瞄准胸部(spine_3骨骼),并检查目标的可视性。 - 武器偏好: Bot 会随机选择偏好的武器,例如 CT 队伍的 Bot 可能更喜欢使用 USP 和 M4A1-S,而不是 P2000 和 M4A4。甚至会尝试购买 CZ75。
3.2. 经济管理与武器购买策略
普通的 CS:GO Bot 购买行为很呆板,这个插件大大提升了它们的经济管理能力:
- 智能防具与拆弹器购买: 在购买区内,如果 Bot 护甲不足或没有头盔,它会自动购买重型防弹衣和头盔。作为 CT 队员,如果没有拆弹器也会立即购买。
-
手枪局与经济局优化:
- 手枪局(第0/12回合): Bot 有机会购买轻型防弹衣或 P250/Dual Berettas,不再盲目购买主武器。
- 经济局(Eco Round): 如果 Bot 金钱不足但拥有次要武器,它们将优先购买手雷或防具。如果金钱低于
bot_eco_limit且没有主武器,它们会购买更强力的手枪(P250, Tec9, Deagle),而不会浪费钱购买主武器。
- 智能丢枪(Drop Weapon): 如果一个 Bot 经济良好但已经有主武器,而附近的队友 Bot 经济不好且没有主武器,有钱的 Bot 会瞄准队友,然后丢下自己的主武器并让队友捡起来。这模拟了人类玩家的共享经济行为。
- 随机购买手雷套装: 开局 6 秒后,Bot 会从几种预设的手雷组合中随机选择一个购买(例如:烟雾弹+2闪光弹+HE弹,或烟雾弹+2闪光弹+燃烧弹)。
3.3. C4/人质场景 AI 改进
在特殊游戏模式下,Bot 的目标意识更强:
-
C4 定时炸弹处理: 只要 C4 被放置,CT 队伍的 Bot 就会意识到并寻找前往 C4 位置的最快路径(
Timer_MoveToBomb),尤其是当它们是仅存的 CT 队员时。它们甚至会切换到小刀加快移动。 - Bot 士气调整: 在炸弹或人质模式中,如果 Bot 处于攻方(T 在炸弹模式或 CT 在人质模式),它们的士气会被降低(-3),促使它们更积极地行动。在半场切换后,士气会恢复。
- 阻止 Bot 换枪来专注于目标: 当 Bot 正在拆弹、使用实体(如开门)、拾取人质或安装炸弹时,它们会暂时被阻止切换武器,以确保专注于当前任务。
3.4. 投掷物利用
Bot 不再只是随意扔雷,它们变得更具策略性:
-
预设投掷点(
bot_nades.txt): 这是一个非常强大的功能。插件允许你为每张地图配置多个预设的投掷点,包括投掷位置、视角、抛物线轨迹和投掷物类型(烟雾弹、燃烧弹等),甚至可以关联一个 BotMimic 的录像文件(.rec)。Bot 会根据这些预设进行投掷,例如投掷开局烟雾。 - 根据声音投掷: 当 Bot 听到附近的枪声或噪音时,有几率向噪音源投掷手雷,甚至会尝试通过调整抛物线来绕过障碍物。
- BotMimic 模仿投掷: 插件与 BotMimic 插件结合,这意味着你录制Bot投掷手雷的动作后,这些AI Bot可以完全复刻你的投掷过程,包括移动到指定位置、调整视角、投掷手雷等。这使得预设投掷物的功能极其强大和逼真。
3.5. 高级移动与射击策略
Bot 的移动和射击行为更加“人类化”:
- 瞄准压枪与急停(AutoStop): 当 Bot 瞄准敌人准备射击时(尤其是在中近距离),它会尝试进行“急停”(AutoStop),模仿人类玩家在射击时停下以提高精准度的行为。
-
狙击枪开镜与切枪: Bot 使用狙击枪(AWP, SSG08)时,会智能地决定开镜级别。射击后,它们会执行快速切换武器的操作(
quick-switch),这不仅是视觉效果,也能帮助它们更快地再次射击。 - Crouch Peek(蹲姿探点): Bot 在射击敌人时,有机会自动蹲伏,类似于人类玩家的“控枪”和“低身位”射击。
-
NavMesh 路径属性利用: 插件会检查当前导航网格区域的属性(
NAV_MESH_WALK或NAV_MESH_RUN),并让 Bot 相应地决定是走路(潜行)还是跑步,这能让 Bot 在关键区域进行更隐蔽的移动。 - 拾取地面武器: Bot 会智能识别地面上更高级别的武器(例如 AK47, M4A1, Deagle 等),如果它们当前装备的武器较差,会尝试跑过去拾取。
3.6. 团队花名册与职业选手模拟
通过自定义命令和配置文件,你可以让 Bot 组成特定的“战队”:
-
team控制台命令: 这个自定义命令允许你快速加载预设的 Bot 团队。例如,你可以定义一个“NaVi”战队,里面包含 s1mple, ZywOo 等 Bot。 -
bot_rosters.txt: 这个配置文件用于定义不同的 Bot 团队,包括团队名称、成员列表和团队 Logo。 -
赛事模式下的特殊处理: 插件会检测游戏是否处于竞技模式(
game_mode 1 && game_type 0),并根据回合数和分数调整一些 Bot 行为,例如在半场或赛点局强制 Bot 进行全面购买。
4. 函数实现原理
本节将深入探讨插件中使用的核心 SourceMod 编程概念和函数,了解这些功能是如何实现上述智能表现的。
4.1. 事件钩子 (Event Hooks)
插件通过监听游戏事件来触发相应的 Bot 行为。这是 SourceMod 插件最基本的交互方式。当游戏内发生特定事件(如玩家重生、回合开始)时,插件中预先定义的函数就会被调用。
代码示例:监听游戏事件
public void OnPluginStart()
{
HookEventEx("player_spawn", OnPlayerSpawn);
HookEventEx("round_prestart", OnRoundPreStart);
// ... 其他事件
}
public void OnPlayerSpawn(Event eEvent, const char[] szName, bool bDontBroadcast)
{
// 当有玩家(包括 Bot)重生时执行
int client = GetClientOfUserId(eEvent.GetInt("userid"));
SetPlayerTeammateColor(client); // 设置队员颜色
// ... 更多重生逻辑
}
HookEventEx("player_spawn", OnPlayerSpawn);:表示当 Source 引擎触发player_spawn事件时,调用插件中的OnPlayerSpawn函数。- 插件监听了包括:玩家重生 (
player_spawn)、回合准备 (round_prestart)、回合开始 (round_start)、回合结束 (round_end)、冻结时间结束 (round_freeze_end)、武器开镜 (weapon_zoom) 和武器开火 (weapon_fire) 等事件。 - 通过这些事件,插件能够:
- 在玩家重生时设置 Bot 的属性、偏好。
- 在回合开始和冻结时间结束时调整 Bot 的购买策略和行为模式。
- 在武器开火时,尤其狙击枪射击后,触发 Bot 的快速切枪动作。
4.2. SDK 调用 (SDK Calls)
SDK 调用是 SourceMod 插件与游戏引擎底层 C++ 函数直接交互的一种高级方式。它允许插件执行游戏内部的私有或保护函数,从而实现对游戏行为的深度控制。这些调用通常依赖于一个 .games 配置文件来获取函数在内存中的地址和参数签名。
代码示例:SDK 调用初始化 & 实际使用
public void LoadSDK()
{
GameData hGameConfig = new GameData("botstuff.games");
// ... 获取各种偏移量和函数签名
// 示例:获取 Bot 移动函数
StartPrepSDKCall(SDKCall_Player);
PrepSDKCall_SetFromConf(hGameConfig, SDKConf_Signature, "CCSBot::MoveTo");
PrepSDKCall_AddParameter(SDKType_Vector, SDKPass_Pointer);
PrepSDKCall_AddParameter(SDKType_PlainOldData, SDKPass_Plain);
g_hBotMoveTo = EndPrepSDKCall(); // 保存函数句柄
// ... 其他 SDK 调用
}
public void BotMoveTo(int client, float fOrigin[3], RouteType routeType)
{
SDKCall(g_hBotMoveTo, client, fOrigin, routeType); // 直接调用 Bot 内部移动函数
}
SDKCall(g_hBotMoveTo, client, fOrigin, routeType);:直接调用 CS:GO 内部的CCSBot::MoveTo函数,让 Bot 移动到指定位置,并选择移动类型(比如快速路线)。- 插件使用了大量的 SDK Call 来实现 Bot 的核心行为:
CCSBot::MoveTo:控制 Bot 移动。CBaseAnimating::LookupBone/GetBonePosition:获取玩家模型的骨骼位置,用于精确瞄准。CCSBot::IsVisible/IsAtHidingSpot:判断 Bot 是否能看到某个点/敌人,或者是否处于掩体后。CCSBot::EquipBestWeapon:让 Bot 切换到最佳武器。CCSBot::SetLookAt:让 Bot 瞄准某个特定点或实体,这在处理投掷物、拆弹和捡枪时非常关键。CBotManager::IsLineBlockedBySmoke:判断视线是否被烟雾弹阻挡,用于智能投掷。CCSBot::BendLineOfSight:调整 Bot 的视线以实现曲线投掷。CCSBot::ThrowGrenade:控制 Bot 投掷手雷的具体动作。CBasePlayer::AddAccount:直接给玩家(Bot)加钱。SetCrosshairCode:直接设置 Bot 的准星代码。Weapon_Switch:强制 Bot 切换武器。
botstuff.games文件:这个文件是 SDK Call 的“字典”,它告诉 SourceMod 如何找到 CS:GO 游戏代码中特定函数的内存地址和它们的参数类型、返回值类型。这是一个与游戏版本紧密相关的文件,不同游戏版本可能需要不同的.games文件。
4.3. 动态绕道 (Detours)
动态绕道是一种更强大的 SDK 交互方式。它允许插件“拦截”游戏内部的某个函数调用,在原函数执行之前(Pre-Hook)或之后(Post-Hook),或者完全取代原函数(Supercede),插入自定义的逻辑。
代码示例:动态绕道初始化 & 被绕道函数
public void LoadDetours()
{
GameData hGameData = new GameData("botstuff.games");
DynamicDetour hBotSetLookAtDetour = DynamicDetour.FromConf(hGameData, "CCSBot::SetLookAt");
hBotSetLookAtDetour.Enable(Hook_Pre, CCSBot_SetLookAt); // 在原函数执行前调用 CCSBot_SetLookAt
// ... 其他 Detours
}
public MRESReturn CCSBot_SetLookAt(int client, DHookParam hParams)
{
char szDesc[64];
DHookGetParamString(hParams, 1, szDesc, sizeof(szDesc));
if (strcmp(szDesc, "Avoid Flashbang") == 0)
{
DHookSetParam(hParams, 3, PRIORITY_HIGH); // 修改 Avoid Flashbang 的优先级
return MRES_ChangedHandled; // 表示已修改参数并处理
}
// ... 其他逻辑
}
- 插件主要使用 Detour 来修改 Bot 的核心行为:
CCSBot::SetLookAt:通过拦截这个函数,插件可以修改 Bot 瞄准点的描述、优先级、持续时间等,实现精确控制。例如,它改变了 Bot 面对闪光弹时的反应优先级,或插入了投掷手雷的逻辑。CCSBot::PickNewAimSpot:在 Bot 选择新瞄准点之后(Post-Hook),插件可以强制 Bot 根据“专业 Bot”逻辑选择最佳瞄准点(头部或脊柱)。BotCOS/BotSIN:这两个函数是游戏内部计算角度余弦值和正弦值的,通过MRES_Supercede完全取代它们并返回 0,这可能是在禁用或修改 Bot 某些内在的数学计算,以达到插件期望的更“人类化”或更“精确”的瞄准效果。这是一种非常激进的修改方式。CCSBot::GetPartPosition:修改 Bot 获取身体部位位置的逻辑,强制将头部向上修正 4 个单位,让 Bot 更容易瞄头。
MRESReturn:Detour 函数的返回值类型,决定了对原函数的影响。MRES_Ignored:忽略插件的修改,继续执行原函数。MRES_Supercede:完全取代原函数,原函数不会执行。MRES_ChangedHandled:插件已修改参数并处理,原函数会继续执行,但使用修改后的参数。MRES_Override:返回自定义值并跳过原函数(用于 Post-Hook)。
4.4. 属性操控 (Prop Manipulation)
Source 引擎中的实体(如玩家、武器、C4)都有各种“属性”(Properties),这些属性存储了实体当前的状态和数据。SourceMod 允许插件读取和修改这些属性。
代码示例:获取和设置属性
// 获取玩家的经济 (m_iAccount 是经济属性)
int iAccount = GetEntProp(i, Prop_Send, "m_iAccount");
// 设置 Bot 的士气 (g_iBotMoraleOffset 是一个预先获取的士气属性的偏移量)
SetEntData(i, g_iBotMoraleOffset, -3);
// 获取 Bot 是否在购买区 (m_bInBuyZone 是一个布尔属性)
bool bInBuyZone = !!GetEntProp(i, Prop_Send, "m_bInBuyZone");
GetEntProp/SetEntProp:用于通过属性名称或偏移量读取和写入实体属性。FindSendPropInfo/GetOffset:用于在插件启动时查找所需属性的偏移量,这样在运行时可以直接使用偏移量进行快速访问,性能更优。- 插件通过属性操控实现了:
- 读取 Bot 经济、护甲、武器信息、当前任务、姿态等。
- 修改 Bot 的士气、瞄准目标点、射击时间戳、瞄准角度等。
- 获取游戏规则 (
GameRules) 的属性,如当前回合数、比分、游戏阶段等,用于判断比赛状态和调整 Bot 行为。
4.5. 定时器 (Timers)
定时器允许插件在未来的某个时间点或以一定频率重复执行某个函数。这对于需要持续检查状态或定期执行任务的功能非常有用。
代码示例:创建定时器
public void OnMapStart()
{
CreateTimer(1.0, Timer_CheckPlayer, _, TIMER_REPEAT | TIMER_FLAG_NO_MAPCHANGE); // 每1秒执行一次
CreateTimer(0.1, Timer_MoveToBomb, _, TIMER_REPEAT | TIMER_FLAG_NO_MAPCHANGE); // 每0.1秒执行一次
// ...
}
CreateTimer:创建定时器。Timer_CheckPlayer:定时检查 Bot 的经济和购买情况。Timer_MoveToBomb:定时检查 C4 状态,并让 CT Bot 移动到 C4 位置。Timer_DropWeapons:在竞技模式下,定时检查 Bot 的丢枪需求。Timer_EnableSwitch/Timer_DontForceThrow:这些是短时一次性定时器,用于在特定操作(如拆弹、安装 C4、投掷手雷)结束后恢复 Bot 的武器切换能力或停止强制投掷。
4.6. 配置数据 (KeyValues & JSON)
插件使用 KeyValues (标准的 Valve 配置文件格式) 和 JSON (一种轻量级的数据交换格式) 来存储和读取外部配置数据。这使得用户无需修改源代码就能自定义插件行为。
代码示例:读取 KeyValues & JSON 文件
public Action Command_Team(int client, int iArgs)
{
// ...
KeyValues kv = new KeyValues("Teams");
if (!kv.ImportFromFile(szPath)) // 从 bot_rosters.txt 读取
{
// ... 错误处理
}
// ...
}
bool IsProBot(const char[] szName, char[] szCrosshairCode, int iSize)
{
// ...
JSONObject jData = JSONObject.FromFile(szPath); // 从 bot_info.json 读取
if(jData.HasKey(szName))
{
JSONObject jInfoObj = view_as(jData.Get(szName));
jInfoObj.GetString("crosshair_code", szCrosshairCode, iSize);
// ...
}
// ...
}
KeyValues用于读取configs/bot_rosters.txt(团队花名册) 和configs/bot_nades.txt(预设投掷物)。JSON则用于读取data/bot_info.json(职业选手信息和准星代码)。- 这种设计让插件拥有很高的可配置性,用户可以通过编辑这些文本文件来定制自己 Bot 的行为。
4.7. 导航网格 (NavMesh)
navmesh 是 Source 引擎游戏中 Bot 寻路和理解地图布局的核心组件。它定义了 Bot 可以在地图上行走、跳跃、蹲伏、躲藏的区域。
代码示例:获取 NavMesh 属性
g_pCurrArea[client] = NavMesh_GetNearestArea(g_fBotOrigin[client]); // 获取 Bot 当前所在区域
if(g_pCurrArea[client] != INVALID_NAV_AREA)
{
if (g_pCurrArea[client].Attributes & NAV_MESH_WALK) // 检查区域是否有步行属性
iButtons |= IN_SPEED; // 保持步行
if (g_pCurrArea[client].Attributes & NAV_MESH_RUN) // 检查区域是否有奔跑属性
iButtons &= ~IN_SPEED; // 取消步行(即奔跑)
}
- 插件利用
NavMesh_GetNearestArea获取 Bot 当前所处的 NavMesh 区域。 - 通过读取该区域的属性(如
NAV_MESH_WALK或NAV_MESH_RUN),插件可以决定 Bot 应该走路(潜行)还是跑步,使其移动更智能。 NavMesh_GetGroundHeight用于获取地面高度,这在处理投掷物抛物线时非常实用。
4.8. 机器人模仿 (BotMimic)
BotMimic 是一个 SourceMod 扩展,允许记录和回放玩家的动作,以供 Bot 模仿。这在实现复杂、精确的动作(如预设投掷物)时非常有用。
代码示例:播放 BotMimic 录像
if(view_as(GetEntData(client, g_iBotLookAtSpotStateOffset)) == LOOK_AT_SPOT && fSpeed == 0.0 && (GetEntityFlags(client) & FL_ONGROUND))
BotMimic_PlayRecordFromFile(client, g_szReplay[g_iDoingSmokeNum[client]]);
- 插件通过
BotMimic_PlayRecordFromFile播放预先录制好的.rec文件。这些录像记录了 Bot 移动到投掷点、调整视角并投掷的全过程。 - 当 Bot 成功到达预设的投掷位置并瞄准到目标点时,它就会播放相应的 BotMimic 录像来完成投掷动作。
- 当 BotMimic 录像播放完毕后,
BotMimic_OnPlayerStopsMimicing事件被触发,插件会清除 Bot 的投掷任务状态。
5. 哪些参数可以自己改变?
这个插件的一大优势就是其高度的可配置性。小白用户也能通过修改几个简单的文件来实现强大的自定义功能!
5.1. 爆头率修改:让 Bot 瞄准更精准
如果你想调整 Bot 的爆头率,使其更具挑战性或更符合你的需求,可以通过修改插件的源代码来实现。以下是你需要关注和修改的部分:
重要提示: 修改源代码需要重新编译插件。在进行任何修改之前,建议备份原始的 .sp 文件。
文件路径: addons/sourcemod/scripting/bot_stuff_manico_20250813.sp
修改位置: 找到函数 public void SelectBestTargetPos(int client, float fTargetPos[3])。
在这个函数内部,你会找到一个 switch(iDefIndex) 结构,它根据 Bot 当前所持的武器类型来决定瞄准策略。我们需要修改其中的几行代码。
代码片段:爆头率控制核心
public void SelectBestTargetPos(int client, float fTargetPos[3])
{
if(IsValidClient(g_iTarget[client]) && IsPlayerAlive(g_iTarget[client]))
{
int iBone = LookupBone(g_iTarget[client], "head_0");
int iSpineBone = LookupBone(g_iTarget[client], "spine_3");
if (iBone < 0 || iSpineBone < 0)
return;
// 这一行决定了 Bot 最终瞄准身体(true)还是头部(false)
bool bShootSpine = false;
float fHead[3], fBody[3], fBad[3];
GetBonePosition(g_iTarget[client], iBone, fHead, fBad);
GetBonePosition(g_iTarget[client], iSpineBone, fBody, fBad);
fHead[2] += 4.0; // 稍微抬高头部瞄准点
if (BotIsVisible(client, fHead, false, -1))
{
if (BotIsVisible(client, fBody, false, -1))
{
if (!IsValidEntity(g_iActiveWeapon[client])) return;
int iDefIndex = GetEntProp(g_iActiveWeapon[client], Prop_Send, "m_iItemDefinitionIndex");
switch(iDefIndex)
{
// 步枪、冲锋枪、霰弹枪、机枪等常见武器的定义索引
// 7: AK47, 8: AUG, 10: Famas, 13: GalilAR, 14: M4A4, 16: M4A1-S, 17: MAC-10, 19: P90
// 23: MP5SD, 24: UMP-45, 25: XM1014, 26: Bizon, 27: MAG-7, 28: MP9, 29: Nova
// 33: Negev, 34: M249, 35: Sawed-Off, 39: SG553, 60: Glock (默认Bot拿Glock也会走到这里)
case 7, 8, 10, 13, 14, 16, 17, 19, 23, 24, 25, 26, 27, 28, 29, 33, 34, 35, 39, 60:
{
float fTargetDistance = GetVectorDistance(g_fBotOrigin[client], fHead);
// ******** 这是核心修改点 (对于大部分武器) ********
// 原始代码: if (IsItMyChance(70.0) && fTargetDistance < 2000.0)
// 这意味着在 2000 单位距离内,Bot 有 70% 的机会瞄准身体(bShootSpine = true)。
// 换言之,默认爆头率是 30% (100% - 70%)。
// 要提高爆头率:
// 1. 降低 IsItMyChance() 中传入的百分比值。
// 例如,改为 IsItMyChance(50.0) -> 50% 爆头率
// 改为 IsItMyChance(20.0) -> 80% 爆头率
// 改为 IsItMyChance(0.0) -> 100% 爆头率 (如果头部可见且在距离内)
if (IsItMyChance(70.0) && fTargetDistance < 2000.0) // <-- 在这里修改数字 (默认 70.0)
bShootSpine = true;
}
// 狙击枪 (AWP: 9, SSG08: 38), 左轮 (11)
// 提醒:Deagle (1) 原始代码中未被明确包含在此处,建议将其添加到狙击枪的策略中
case 1, 9, 11, 38: // <-- 如果需要,在此处添加 '1' (Deagle 的 iDefIndex)
{
// ******** 这是狙击枪/沙鹰等武器的修改点 ********
// 原始代码: bShootSpine = true;
// 这意味着这些武器默认总是瞄准身体(0% 爆头率)。
// 如果想让这些武器也能爆头:
// 1. 设置为 false,强制 100% 爆头率 (如果头部可见)
// bShootSpine = false;
// 2. 使用 IsItMyChance() 设置爆头概率
// bShootSpine = !IsItMyChance(X.0); // X 为不爆头的几率
// 例如:bShootSpine = !IsItMyChance(50.0); // 50% 爆头率
bShootSpine = true; // <-- 在这里修改
}
}
}
}
else
{
//Head wasn't visible, check other bones.
for (int b = 0; b <= sizeof(g_szBoneNames) - 1; b++)
{
iBone = LookupBone(g_iTarget[client], g_szBoneNames[b]);
if (iBone < 0)
return;
GetBonePosition(g_iTarget[client], iBone, fHead, fBad);
if (BotIsVisible(client, fHead, false, -1))
break;
else
fHead[2] = 0.0;
}
}
if(bShootSpine)
fTargetPos = fBody;
else
fTargetPos = fHead;
}
}
bShootSpine变量: 这是一个布尔变量,如果为true,Bot 将瞄准敌人的脊柱(即身体部位);如果为false,则瞄准头部。插件的目标是将其设置为false来提高爆头率。IsItMyChance(float fChance): 这是一个辅助函数,它会生成一个 0 到 100 之间的随机浮点数,并判断这个随机数是否小于或等于你传入的fChance值。- 如果
IsItMyChance(70.0),那么有 70% 的概率返回true。 - 在当前代码中,
if (IsItMyChance(70.0) && fTargetDistance < 2000.0) bShootSpine = true;表示在指定距离内,有 70% 的几率让bShootSpine为true(瞄准身体)。这意味着只有 30% (100% - 70%) 的几率bShootSpine保持为false(瞄准头部)。 - 要提高大部分武器的爆头率,你需要**降低**
IsItMyChance()中传入的数字。
- 如果
- 狙击枪/沙鹰等特殊武器: 原始代码中,对于狙击枪和左轮手枪(Case 9, 11, 38),
bShootSpine被硬编码为true,这意味着这些武器默认是瞄准身体的(0% 爆头率)。- 针对沙鹰(weapon_deagle),其
iDefIndex是1,原始代码中未将其包含在该case列表中,这可能导致沙鹰的爆头行为不一致。建议将其添加到 `case` 列表中以统一管理。 - 如果你希望这些武器也能爆头,你需要修改
bShootSpine = true;这一行,例如改为bShootSpine = false;来强制 100% 爆头,或者使用bShootSpine = !IsItMyChance(X.0);来设置爆头概率。
- 针对沙鹰(weapon_deagle),其
通过这种方式,你可以精确调整 Bot 的爆头率,使其更符合你的期望,无论是变得更强还是更弱。
5.2. configs/bot_rosters.txt (团队花名册)
这个文件允许你定义自定义的 Bot 战队,并指定他们的成员和团队 Logo。
文件路径与示例内容:addons/sourcemod/configs/bot_rosters.txt
"Teams"
{
"Astralis"
{
"players" "dupreeh,Xyp9x,device,gla1ve,Magisk"
"logo" "valve_astralis" // 团队Logo的代码,可以在CS:GO Wiki或游戏中找到
}
"NaVi"
{
"players" "s1mple,ZywOo,NiKo,sh1ro,jL" // 这里可以列出 bot_info.json 中定义的职业选手名字
"logo" "valve_navi"
}
"MyCustomTeam" // 你自己的自定义团队
{
"players" "Bot01,Bot02,Bot03,Bot04,Bot05" // 任意 Bot 名字,除非在 bot_info.json 中有定义,否则就是普通 Bot
"logo" "" // 如果不设置,可以留空
}
}
"Teams": 根节点,必须存在。"TeamName": 每个子节点代表一个队伍的名称,例如"Astralis","NaVi"。你可以自定义团队名称。"players": 逗号分隔的 Bot 名字列表。这些名字将用于添加 Bot。如果名字与bot_info.json中的职业选手匹配,这些 Bot 将获得增强。"logo": 这是一个 Steam 团队 Logo 的内部代码。例如valve_astralis,valve_navi。你可以在网上找到很多,或在游戏中通过mp_teamlogo_1/mp_teamlogo_2命令尝试。
使用方法: 在游戏中打开控制台,输入 team <TeamName> <t|ct>。
例如:team NaVi t 会将 NaVi 战队的 Bot 加入 T 方。
team Astralis ct 会将 Astralis 战队的 Bot 加入 CT 方。
5.3. configs/bot_nades.txt (预设投掷物)
这个文件允许你为不同的地图定义 Bot 在特定位置投掷特定手雷的动作。
文件路径与示例内容:addons/sourcemod/configs/bot_nades.txt
"Nades"
{
"de_dust2" // 地图名称
{
"SmokeMid" // 自定义名称
{
"position" "-57.070797 2139.697498 -16.030310" // Bot 走到这个位置
"lookat" "-141.040186 2115.118945 90.729111" // Bot 瞄准这个点进行投掷
"nadedefindex" "43" // 投掷物 ID:43为烟雾弹 (smokegrenade)
"replay" "dust2_mid_smoke.rec" // BotMimic 录像文件名 (位于 /addons/sourcemod/data/botmimic/ 目录)
"timestamp" "10.0" // 每多少秒可以重复投掷一次(此功能在此插件中被 RoundEnd 重置)
"team" "T" // 哪个队伍的 Bot 投掷
}
"MolotovShort"
{
"position" "142.123 200.456 0.0"
"lookat" "150.789 220.123 50.0"
"nadedefindex" "44" // 44为燃烧弹 (molotov) / 48为燃烧瓶 (incgrenade)
"replay" "dust2_short_molotov.rec"
"timestamp" "15.0"
"team" "T"
}
}
"de_mirage"
{
"SmokeCTSpawn"
{
"position" "-123.456 789.012 10.0"
"lookat" "-130.000 800.000 60.0"
"nadedefindex" "43"
"replay" "mirage_ct_smoke.rec"
"timestamp" "12.0"
"team" "CT"
}
}
}
"Nades": 根节点。"map_name": 键为地图文件名,例如"de_dust2"。"CustomName": 地图下的子键,为这个投掷点自定义一个名称,例如"SmokeMid"。"position": Bot 必须走到这个 X Y Z 坐标位置才能开始投掷。"lookat": Bot 投掷时瞄准的 X Y Z 坐标。"nadedefindex": 投掷物的内部 ID。43: 烟雾弹 (weapon_smokegrenade)44: 燃烧弹 (weapon_molotov)48: 燃烧瓶 (weapon_incgrenade)46: 闪光弹 (weapon_flashbang)45: 高爆手雷 (weapon_hegrenade)47: 诱饵弹 (weapon_decoy)
"replay": BotMimic 扩展录制的.rec文件名(不含路径),例如"dust2_mid_smoke.rec"。你需要自己录制这些文件并放置在addons/sourcemod/data/botmimic/目录下。"timestamp": 在一个回合中,Bot 间隔多长时间才能再次尝试投掷(此功能在此插件中被 RoundEnd 重置)。"team": 哪个队伍的 Bot 负责投掷。输入"T"或"CT"。
重要提示: 要使用此功能,你服务器上必须安装 BotMimic 插件。
录制 .rec 文件需要一些技巧:作为人类玩家,在游戏中启用 BotMimic 录制,运行到指定 position,瞄准 lookat 点并完成投掷动作,然后停止录制,将文件命名为 replay 中指定的名称。
5.4. data/bot_info.json (职业选手信息)
这个 JSON 文件存储了插件中识别的“职业 Bot”的具体设置,主要是他们的准星代码。注意以下是伪代码,实际格式看文件。
文件路径与示例内容:addons/sourcemod/data/bot_info.json
{
"s1mple": {
"crosshair_code": "CSGO-s1mple-crosshair-code-here" // 实际的准星代码
},
"ZywOo": {
"crosshair_code": "CSGO-ZywOo-crosshair-code-here"
},
"NiKo": {
"crosshair_code": "CSGO-NiKo-crosshair-code-here"
},
"sh1ro": {
"crosshair_code": "CSGO-sh1ro-crosshair-code-here"
},
"donk": {
"crosshair_code": "CSGO-donk-crosshair-code-here"
},
"m0NESY": {
"crosshair_code": "CSGO-m0NESY-crosshair-code-here"
}
}
"PlayerName": 键为 Bot 的名字(需要与bot_rosters.txt或你用于bot_add的名字完全匹配)。"crosshair_code": 该职业选手使用的准星代码。你可以从 ProSettings 等网站找到这些代码。
注意: s1mple, ZywOo, NiKo, sh1ro, jL, donk, m0NESY 这几个名字的 Bot 被插件硬编码了额外的“超能力”:他们的 g_fLookAngleMaxAccel 被设置为 20000.0,g_fReactionTime 被设置为 0.0,g_fAggression 被设置为 1.0。这意味着他们的瞄准速度极快,反应时间为零,并且极具攻击性。
其他在 bot_info.json 中定义但不在上述列表中的 Bot,其 ReactionTime, Aggression 和 LookAngleMaxAccel 将会是随机且较高的数值,但不如硬编码的这些Bot那么极端。
5.5. 插件内置变量(修改源代码)
虽然不推荐小白直接修改源代码,但如果你想进行更深度的自定义,可以找到以下与 Bot 行为相关的布尔变量,并尝试修改它们的初始化值。
相关代码行:在 OnClientPostAdminCheck 函数中
public void OnClientPostAdminCheck(int client)
{
// ...
g_bUseUSP[client] = IsItMyChance(75.0); // CT Bot 有75%几率倾向使用 USP
g_bUseM4A1S[client] = IsItMyChance(50.0); // CT Bot 有50%几率倾向使用 M4A1-S
g_bUseCZ75[client] = IsItMyChance(20.0); // Bot 有20%几率倾向购买 CZ75
// ...
}
- 这些变量控制了 Bot 对特定武器的偏好。
IsItMyChance(float fChance)是一个判断随机几率的辅助函数。 - 如果你想让所有 Bot 都使用 USP,可以改成
g_bUseUSP[client] = true;。如果你想完全禁用某个偏好,则设为false;。 - 修改后需要重新编译
.sp文件为.smx文件。
5.6. 控制台变量 (Cvars)
插件会读取和影响一些 CS:GO 内置的控制台变量。
-
bot_eco_limit: 这个 Cvar 控制 Bot 在经济局最低的经济限制。插件会根据游戏阶段(特别是竞技模式的赛点局或半场局)动态地将它设置为 0 或 3000。- 你可以通过
sm_cvar bot_eco_limit <value>在控制台修改。 - 如果插件判断为“强制购买”回合(
ShouldForce()),它会强制把bot_eco_limit设置为 0,让 Bot 不受经济限制地购买。
- 你可以通过
-
game_mode/game_type: 插件通过这些 Cvar 判断是否处于竞技模式。 -
mp_halftime/mp_maxrounds/mp_overtime_maxrounds/mp_match_can_clinch: 插件通过这些 Cvar 判断游戏的回合规则和是否处于半场、赛点或加时赛,从而触发 Bot 的强制购买行为。 -
weapon_recoil_scale: 插件在计算瞄准压枪时会用到这个 Cvar 的值。通常你不需要修改它,除非你想全局调整后坐力效果。
6. 安装与使用 (小白必看!)
按照以下步骤,即使是小白也能轻松安装和使用这个强大的 Bot 增强插件。
6.1. 前置条件
- SourceMod & MetaMod: 确保你的 CS:GO 服务器已经安装了最新版本的 SourceMod 和 MetaMod:Source。这是 SourceMod 插件运行的基础。
- 其他插件: 请参考Manico's Edition,确保安装所有依赖插件。
6.2. 插件安装
-
将提供的
bot_stuff_manico_20250813.sp文件编译成.smx文件。如果你不熟悉编译,可以直接下载已经编译好的.smx文件(通常在插件发布页面会提供)。如何编译: 将
.sp文件放在addons/sourcemod/scripting/文件夹中。在服务器控制台或本地客户端启动 CS:GO,并确保 SourceMod 正常加载。然后输入sm_compile bot_stuff_manico_20250813.sp。如果成功,会在addons/sourcemod/plugins/目录下生成bot_stuff_manico_20250813.smx。 -
将编译好的
bot_stuff_manico_20250813.smx文件上传到你 CS:GO 服务器的csgo/addons/sourcemod/plugins/目录下。
6.3. 配置文件夹设置
以下文件夹的存在,是让插件能够加载自定义数据。如果你正确安装了,他们应该已经存在。如果没有,请按照以下步骤创建和配置。
-
在
csgo/addons/sourcemod/configs/目录下创建bot_rosters.txt文件(参照上文 5.2 章节)。 -
在
csgo/addons/sourcemod/configs/目录下创建bot_nades.txt文件(参照上文 5.3 章节)。 -
在
csgo/addons/sourcemod/data/目录下创建bot_info.json文件(参照上文 5.4 章节)。 -
在
csgo/addons/sourcemod/gamedata/目录下创建botstuff.games文件。这个文件通常由插件作者提供;如果没有,插件将无法正常工作,因为它需要知道游戏内部函数的内存地址。你可能需要从插件的 GitHub 仓库或发布页面下载此文件。通常,
.games文件是针对特定游戏版本编译的。虽然游戏不再更新了,但一些插件是在老的游戏版本编译的,所以上古版本可能会失效或导致服务器崩溃。 -
如果你使用
bot_nades.txt中的"replay"功能,确保在csgo/addons/sourcemod/data/botmimic/目录下放置对应的.rec文件。你需要自己录制这些文件。
6.4. 使用 team 命令
安装并配置好插件后,就可以在服务器上愉快地玩耍了!
-
重启服务器或刷新插件: 上传文件后,重启你的 CS:GO 服务器,或者在服务器控制台输入
sm plugins refresh来加载新插件。 -
添加 Bot: 在游戏中打开控制台(通常是 ` 键),输入
bot_kick all清除现有 Bot。 -
使用自定义的
team命令来加载你预设的 Bot 团队:team <团队名称> <t|ct>- 例如:
team NaVi t - 例如:
team Astralis ct - 例如:
team MyCustomTeam t
- 观察你的 Bot 们在游戏中表现出惊人的智能行为!
7. 常见问题与排查
-
插件未加载:
- 检查
csgo/addons/sourcemod/plugins/目录下是否有.smx文件。 - 检查服务器控制台日志,是否有 SourceMod 相关的错误信息。
- 确保 MetaMod 和 SourceMod 本身已正确安装并运行(在控制台输入
meta version和sm version)。
- 检查
-
Bot 行为异常或服务器崩溃:
.games文件不兼容: 这是最常见的问题。如果插件更新了,旧的botstuff.games文件可能不再有效。你需要等待插件作者发布更新的.games文件。- 插件错误: 检查在你操作后服务器控制台或
sourcemod/logs中是否有 SourceMod 错误日志。
-
team命令无效:- 检查
configs/bot_rosters.txt文件路径是否正确,内容格式是否符合 KeyValues 标准(括号和引号是否匹配)。 - 命令拼写是否正确:
team <TeamName> <t|ct>。
- 检查
-
Bot 不投掷预设手雷或模仿动作:
- 确保
bot_nades.txt文件路径和格式正确。 - 确保
"replay"中指定的文件名在addons/sourcemod/data/botmimic/目录下存在,且是有效的.rec文件。 - 确认 BotMimic 插件已正确安装和加载。
- 检查
nadedefindex是否正确对应手雷类型。 - Bot 不会每次都投掷,它会等待时机和距离。
- 确保
-
Bot 没有职业选手的准星或超能力:
- 检查
data/bot_info.json文件路径是否正确,内容格式是否符合 JSON 标准。 - 检查 Bot 的名字是否与
bot_info.json中的键完全匹配(大小写敏感)。
- 检查
8. 总结
通过这份详尽的指南,你现在应该对 bot_stuff_manico_20250813.sp 插件的功能、实现原理以及如何自定义它有了全面的了解。这个插件极大地提升了 CS:GO Bot 的智能水平,让它们表现得更像人类玩家,无论是经济管理、策略移动、还是精准射击和投掷,都能带来更具挑战性和趣味性的游戏体验。
尽情享受你的Bot吧!如果在自定义过程中有任何疑问,可以参考本文档或寻求 SourceMod 社区的帮助。