任务族谱(Task Catalogue)
game/task 约 700 个文件、60 万行,包含 400 多个任务类型。本页不逐文件总结,而是按目录给出“族谱”:每个子目录的关键任务类、职责、它们之间的父子/调用关系,以及配套的元数据(Metadata.psc)与管理器;随后对最核心的五个机制给出状态机级说明:战斗(CTaskCombat)、导航跟随(CTaskNavBase/CTaskMoveFollowNavMesh)、上车(CTaskEnterVehicle)、动作/运动(CTaskMotionPed/CTaskHumanLocomotion)以及场景系统(CScenarioManager/CScenarioPointManager/CTaskUseScenario)。
背景与相关页面#
- 任务内核(
aiTaskFSM、任务树、槽位、中止)见 task-system;读本页前建议先读它。 - 事件→响应任务的映射见 events-and-responses。
- 寻路服务(pathserver)见 navigation-and-pathserver。
- NM(NaturalMotion)布娃娃行为的物理侧见 game-physics-and-ragdoll;MoVE 动画网络见 rage-animation-and-move、game-animation-and-ik。
- 载具驾驶任务(
VehicleAI/task)见 vehicle-ai-and-road-network;武器数据见 weapons;通缉/派遣见 wanted-crime-dispatch;行人人口与场景刷人见 ped-intelligence-and-population。
盘点#
| 子目录 | 文件数 | 行数(不含空行,约) | 主题 |
|---|---|---|---|
Combat | 114 | 124k | 战斗、掩体、近战、伤亡、搜索、载具战斗/追逐、战术分析 |
Movement | 87 | 88k | 导航跟随、goto、闲逛移动、攀爬/梯子/翻越/跳跃/坠落、跳伞、喷气背包 |
Vehicle | 49 | 87k | 上下车、车内动作、车载武器、骑马、火车 |
Scenario | 83 | 56k | 场景点、场景类型元数据、场景任务、链/簇、编辑器 |
Motion | 49 | 43k | 动作树任务:人形/动物运动、瞄准动作、游泳、跳伞动作 |
Default | 36 | 38k | 默认/环境任务:玩家、闲逛、未警觉、巡逻、逮捕/手铐、环境片段 |
Physics | 79 | 34k | NM 行为任务、从 NM 混出、附着、起身数据 |
Response | 69 | 30k | 逃跑、惊吓反应、激怒系统、推搡、爆炸反应 |
System | 38 | 29k | 内核(见 task-system) |
Weapons | 42 | 28k | 枪械/瞄准/装弹/换枪/投掷/炸弹 |
Service | 13 | 16k | 警察/SWAT/消防/救护/军队/目击者 |
Animation | 12 | 13k | 脚本动画、同步场景、过场、MoVE 脚本网络 |
General | 13 | 12k | 基础任务、次要任务、手机、序列 |
Crimes | 11 | 3k | 随机事件(犯罪)管理、偷车、追捕 |
Helpers | 6 | 2k | 对话、道具管理、人行道洪泛辅助 |
Debug | 2 | <0.1k | 片段距离测试任务 |
以上数字由本次分析对目录逐文件计数得到(PowerShell Measure-Object -Line,不计空行),仅作规模参考。每个任务目录都有一个 Metadata.psc 定义该目录任务的 Tunables(基类 CTuning),统一由 TaskClassInfo.cpp 引入生成代码 game/task/System/TaskClassInfo.cpp:260-275,加载机制见 task-system §10。
阅读约定:下表“类 < 基类 @行”取自头文件的类声明行;CTaskFSMClone 基类意味着该任务可在网络克隆上运行(见 task-system §9);CTaskMove/CTaskMoveBase/CTaskNavBase 基类意味着它只能进入移动树;CTaskMotionBase 意味着它只能进入动作树。
1. 任务之间的典型组合#
证据:CTaskThreatResponse 创建 CTaskCombat/CTaskSmartFlee game/task/Combat/TaskThreatResponse.cpp:1256、TaskThreatResponse.cpp:1351;CTaskCombat 的各状态创建 CTaskCover、CTaskShootAtTarget、CTaskComplexControlMovement 等(§3.1);CTaskWander 用 CTaskComplexControlMovement(CTaskMoveWander, CTaskAmbientClips) game/task/Default/TaskWander.cpp:600-615;CTaskUseScenario 在 PlayAmbients 中创建 CTaskAmbientClips game/task/Scenario/Types/TaskUseScenario.cpp:4108;CTaskNavBase 跟随路线时创建 CTaskMoveGoToPointAndStandStill 等 goto 子任务 game/task/Movement/TaskNavBase.cpp:4259-4330;CTaskMotionPed 在 OnFoot 创建 CTaskHumanLocomotion game/task/Motion/Locomotion/TaskMotionPed.cpp:1510-1519;心跳与 MBR 写入见 task-system §5.1。
2. 按目录的族谱#
2.1 System(内核)#
CTask、CTaskFSMClone、CTaskMove/CTaskMoveBase、CTaskComplex、树/管理器、CTuning,以及 TaskHelpers.h 中的通用辅助(CTaskTimer、CPathNodeRouteSearchHelper、CGetupProbeHelper、CSimpleBlendHelper、CGenericClipHelper、CFindNearestCarNodeHelper、CCoverPointStatusHelper、CScenarioClipHelper)game/task/System/TaskHelpers.h:151-3760。详见 task-system。
2.2 General(基础/次要/手机/序列)#
| 类 < 基类 | 职责 |
|---|---|
CTaskComplexControlMovement < CTaskComplex @100 | 主树中托管一个移动任务(心跳)并可并行跑一个主子任务;终止条件可选移动结束/子任务结束/任一/全部 game/task/General/TaskBasic.h:100-121 |
CTaskDoNothing < CTask @505 | 默认任务(任务行人/不闲逛的行人) |
CTaskNetworkClone < CTask @64 | 克隆行人的默认任务 |
CTaskUseSequence < CTaskFSMClone @1499、CTaskMoveSequence < CTaskMove @764 | 脚本序列(主任务序列/移动序列) |
CTaskSetCharState 族、CTaskSetPedDefensiveArea、CTaskSetCharDecisionMaker | 设置行人状态/防御区/决策制定器的“瞬时任务” |
CTaskPause、CTaskUninterruptable、CTaskCrouchToggle、CTaskSayAudio、CTaskOpenDoor、CTaskShovePed、CTaskClearLookAt | 杂项基础任务 |
CTaskComplexUseMobilePhone(AndMovement)、CTaskMobilePhone、CTaskCallPolice | 手机行为(含报警) |
CTaskAffectSecondaryBehaviour、CTaskCrouch、CTaskPutOnHelmet/TakeOffHelmet、CTaskAggressiveRubberneck、CTaskGeneralSweep | 次树任务(叠加行为) |
类声明见 TaskBasic.h:33-1736、game/task/General/TaskSecondary.h:33-224、game/task/General/Phone/TaskMobilePhone.h:9、game/task/General/Phone/TaskCallPolice.h:22、game/task/General/TaskVehicleSecondary.h:19、game/task/General/TaskGeneralSweep.h:12。
2.3 Default(默认与环境行为)#
| 类 < 基类 | 职责 |
|---|---|
CTaskPlayerOnFoot < CTask @36 | 本地玩家的根任务:把输入映射为跳跃、近战、换枪、掩体、梯子、开枪、上车、逮捕、骑乘、跳伞/喷气背包脱卸、滑坡等 20 多个状态 game/task/Default/TaskPlayer.h:36-64;它由当前动作任务的 CreatePlayerControlTask() 创建为默认任务(见 task-system §5.1) |
CTaskMovePlayer < CTaskMove @716 | 玩家移动输入→移动树 |
CTaskWander < CTask @34 | 环境闲逛:Wander/CrossRoadAtLights/CrossRoadJayWalking/MoveToShelterAndWait/Crime/BlockedByVehicle… 状态 game/task/Default/TaskWander.h:75-84,内部用 CTaskMoveWander 并可插入场景使用 |
CTaskUnalerted < CTaskFSMClone @27 | 场景/闲逛行人的“未警觉”根任务:在闲逛、搜索场景、沿场景链、使用场景、车内、等待载具着陆、走向消失等状态间切换 game/task/Default/TaskUnalerted.h:87-100;由 CScenarioManager 包装 CTaskUseScenario 生成 game/task/Scenario/ScenarioManager.cpp:5179 |
CTaskAmbientClips < CTaskFSMClone @560 | 基于“条件动画”(CConditionalAnimsGroup)的环境片段/道具播放(场景、闲逛共用) |
CTaskPatrol、CTaskStandGuardFSM、CPatrolNode/CPatrolLink | 巡逻路线与站岗 game/task/Default/Patrol/TaskPatrol.h:50-137、Patrol/PatrolRoutes.h:28-96 |
CTaskArrest、CTaskCuffed、CTaskInCustody、CTaskIncapacitated | 逮捕/手铐/羁押/失能(部分由 ENABLE_TASKS_ARREST_CUFFED、CNC_MODE_ENABLED 等宏控制) |
CTaskChat、CTaskSlopeScramble、CTaskSwimmingWander、CTaskFlyingWander、CTaskWanderInArea | 其他环境行为 |
CAmbientAudioManager、AmbientAnimationManager | 环境对白/动画流送管理(CTask::StaticUpdate 每帧更新环境片段流送)game/task/System/Task.cpp:148-151 |
类声明行见 TaskPlayer.h:36-823、TaskWander.h:34-593、TaskUnalerted.h:27、TaskAmbient.h:560、TaskCuffed.h:41-491、TaskArrest.h:55、TaskIncapacitated.h:12。
2.4 Combat(战斗)#
| 类 < 基类 | 职责 |
|---|---|
CTaskThreatResponse < CTask @31 | 事件处理器产生的威胁响应入口:Analysis 决定战/逃,进入 Combat、Flee 或 ReactAndFlee game/task/Combat/TaskThreatResponse.h:49-66。决策链依次:规则→战斗行为→属性→性格→兜底 TaskThreatResponse.cpp:647-720 |
CTaskCombat < CTaskFSMClone(TaskNewCombat.h)@124 | 主战斗任务(§3.1) |
CTaskCombatFlank、CTaskCombatSeekCover、CTaskCombatChargeSubtask、CTaskSetAndGuardArea、CTaskStandGuard、CTaskSeparate、CTaskCombatClosestTargetInArea、CTaskCombatAdditionalTask(TaskCombat.h) | 旧战斗文件中保留的辅助/子任务;CTaskCombatAdditionalTask 是移动时并行执行的瞄射/手势子任务 game/task/Combat/TaskCombat.h:42-878 |
CTaskCover、CTaskEnterCover、CTaskExitCover、CTaskInCover、CTaskMotionInCover、CTaskAimGunFromCoverIntro/Outro、CTaskAimGunBlindFire、CDynamicCoverHelper | 掩体全流程(TaskCover.cpp 单文件约 3 万行)game/task/Combat/Cover/TaskCover.h:51-4291 |
CCover/CCoverPoint、CCoverFinder(CCoverFinderFSM : CTaskHelperFSM)、CCoverPointFilter* | 掩体点存储:导航网格掩体点 2560 + 脚本掩体点 64,边界区域 40 个 game/task/Combat/Cover/cover.h:757-771;掩体点从 pathserver 后台线程抽取(见导航页) |
CTaskMelee、CTaskMeleeActionResult、CTaskMoveMeleeMovement、CTaskMeleeUpperbodyAnims、CTaskMeleeUninterruptable | 近战(TaskCombatMelee.cpp 约 9.5k 行)game/task/Combat/TaskCombatMelee.h:152-1176 |
CTaskDyingDead、CTaskHitResponse、CTaskComplexOnFire、CTaskDamageElectric、CTaskRevive | 受伤与死亡(TASK_DYING_DEAD 在克隆树上被强制应用)game/task/Combat/TaskDamageDeath.h:98-907 |
CTaskSearch(Base/OnFoot/InAutomobile/InBoat/InHeli)、CTaskInvestigate、CTaskSearchForUnknownThreat | 丢失目标后的搜索与调查 |
CTaskVehicleCombat、CTaskVehiclePersuit、CTaskVehicleChase(+CVehicleChaseDirector)、CTaskBoat*、CTaskHeli*、CTaskPlaneChase、CTaskSubmarine*、CTaskShootOutTire | 载具中的战斗与追逐 |
CTaskAdvance、CTaskCharge、CTaskShootAtTarget、CTaskVariedAimPose、CTaskTargetUnreachable(InInterior/Exterior)、CTaskReactToBuddyShot、CTaskShellShocked、CTaskStealthKill、CTaskDraggingToSafety/DraggedToSafety、CTaskAimFromGround | Combat/Subtasks 中供 CTaskCombat 各状态使用的子任务 |
CTaskWrithe、CTaskToHurtTransit、CTaskReactAimWeapon、CTaskSharkAttack/SharkCircle、CTaskCombatMounted(带骑乘转移表)、CTaskAnimatedHitByExplosion | 其他战斗相关任务 |
CCombatManager(CCombatMountedManager、CCombatMeleeManager、CCombatTaskManager) | 全局:近战组(每组最多 10 个对手)、战斗行人统计(数组 64、联机同时战斗上限 24)game/task/Combat/CombatManager.h:248-289、CombatManager.h:455-496 |
CCombatDirector、CCombatSituation{Normal,FallBack,Lull,Escalate}、CCombatOrders | 一组敌人共享的“导演”:协调射击、局势切换 game/task/Combat/CombatDirector.h:31-70、game/task/Combat/CombatSituation.h:69-139 |
CTacticalAnalysis(导航网格点 64、掩体点 64) | 针对目标的战术点分析,供 CTaskMoveToTacticalPoint 使用 game/task/Combat/TacticalAnalysis.h:399-401、TacticalAnalysis.h:950-973 |
2.5 Response(响应)#
| 类 < 基类 | 职责 |
|---|---|
CTaskSmartFlee < CTaskFSMClone @83 | 主逃跑任务:步行/滑雪/载具三张转移表;状态含下车、步行逃、找掩体蹲伏、回到起点、上车逃/急停/倒车/加速、举手、畏缩 game/task/Response/TaskFlee.h:42-221 |
CTaskEscapeBlast、CTaskScenarioFlee、CTaskFlyAway、CTaskExhaustedFlee、CTaskWalkAway | 其他逃离形式 TaskFlee.h:793-1206 |
CTaskReactAndFlee、CTaskReactInDirection、CTaskReactToExplosion、CTaskReactToImminentExplosion、CTaskReactToDeadPed/CTaskCheckPedIsDead、CTaskDiveToGround、CTaskDuckAndCover、CTaskSidestep、CTaskGrowlAndFlee | 先反应后逃/躲 |
CTaskShockingEvent 及 …Watch/Goto/HurryAway/React/BackAway/StopAndStare/ReactToAircraft/ThreatResponse/Flee、CTaskShockingPoliceInvestigate、CTaskShockingNiceCarPicture | 惊吓事件反应族 game/task/Response/TaskShockingEvents.h:22-1275 |
CTaskAgitated、CTaskAgitatedAction、CTaskConfront、CTaskIntimidate、CTaskShove、CTaskShoved、CTaskGangPatrol | 被冒犯/激怒后的对峙、推搡、挑衅 |
Response/Info/*:CAgitatedManager、CAgitatedAction*(约 35 种)、CAgitatedCondition*(约 90 种)、CAgitatedPersonality/Response/Trigger/State/Say/Situation | 激怒系统的数据驱动行为树:从 common:/data/ai/agitatedpersonalities|agitatedresponses|agitatedtriggers.meta 加载 game/task/Response/Info/AgitatedManager.cpp:38-52;条件/动作类声明见 Info/AgitatedConditions.h:31-1769、Info/AgitatedActions.h:35-903 |
2.6 Movement(移动)#
| 类 < 基类 | 职责 |
|---|---|
CTaskNavBase < CTaskMove @487 → CTaskMoveFollowNavMesh @198、CTaskMoveWander @63 | 基于 pathserver 的路线请求与跟随(§3.2)game/task/Movement/TaskNavBase.h:487、TaskNavMesh.h:198、TaskMoveWander.h:63 |
CTaskUseClimbOnRoute、CTaskUseDropDownOnRoute、CTaskUseLadderOnRoute、CTaskMoveWaitForNavMeshSpecialActionEvent、CTaskMoveReturnToRoute、CTaskMoveGetOntoMainNavMesh | 路线上的特殊动作(由导航任务发事件触发)TaskNavMesh.h:422-719 |
CTaskMoveGoToPoint < CTaskMoveBase @50 及 …OnRoute/AndStandStill/RelativeToEntity…/StandStillAchieveHeading | 直线 goto 的底层移动 game/task/Movement/TaskGotoPoint.h:50-841 |
CTaskMoveStandStill、CTaskMoveAchieveHeading、CTaskMoveFaceTarget、CTaskTurnToFaceEntityOrCoord | 原地/转向 game/task/Movement/TaskIdle.h:12-254 |
CTaskGoToPointAnyMeans、CTaskFollowPatrolRoute、CTaskGetOutOfWater、CTaskGoToScenario 等 | 复合 goto(TaskGoTo.h) |
CTaskFollowLeaderInFormation/AnyMeans、CTaskSeekEntityAiming、CEntitySeekPosCalculator* 模板、CTaskMoveFollowEntityOffset、CTaskMoveBeInFormation、CTaskMoveTrackingEntity | 跟随实体/编队 |
CTaskMoveToTacticalPoint、CTaskMoveWithinAttackWindow、CTaskMoveWithinDefensiveArea、CTaskGoToPointAiming | 战斗中的移动 |
CTaskWalkRoundEntity/Vehicle/VehicleDoor/Fire、CTaskComplexEvasiveStep、CTaskCower、CTaskHitWall | 碰撞/避让响应(多作为移动事件响应) |
Climbing/*:CTaskVault、CTaskDropDown、CTaskClimbLadder、CTaskGoToAndClimbLadder、CTaskRappel/CTaskHeliPassengerRappel、CClimbDetector、CDropDownDetector、CLadderMetadataManager | 攀爬/梯子/降索 |
Jumping/*:CTaskJump、CTaskJumpVault、CTaskFallOver、CTaskFallAndGetUp、CTaskDropOverEdge、CTaskComplexStuckInAir;CTaskFall、CTaskGetUp、CTaskCrawl | 跳跃、坠落、起身 |
CTaskParachute/CTaskParachuteObject、CTaskJetpack/CJetpack | 跳伞与喷气背包 |
CTaskFollowWaypointRecording、CTaskSlideToCoord、CTaskTakeOffPedVariation、CTaskFlyToPoint、CTaskGenericMoveToPoint、CTaskAnimatedFallback | 其他 |
2.7 Motion(动作树)#
所有类继承 CTaskMotionBase(动作状态接口 SupportsMotionState/IsInMotionState、移动速度、备用片段等)game/task/Motion/TaskMotionBase.h:34-140:CTaskMotionPed/CTaskMotionPedLowLod(人形根)、CTaskHumanLocomotion、CTaskMotionAiming(+Transition)、CTaskMotionStrafing、CTaskMotionSwimming/CTaskMotionDiving、CTaskMotionParachuting、CTaskMotionJetpack、CTaskMotionDrunk、CTaskRepositionMove、CTaskCombatRoll、CTaskMotionInTurret,以及动物:CTaskMotionAnimal、四足/鸟/鱼/马/狗/鹿运动任务(TaskQuadLocomotion、TaskBirdLocomotion…)。载具内动作任务 CTaskMotionInVehicle/InAutomobile/OnBicycle 在 Vehicle/TaskInVehicle.h game/task/Vehicle/TaskInVehicle.h:130-1803。§3.4 详述。
2.8 Vehicle(车辆/骑乘/火车)#
| 类 < 基类 | 职责 |
|---|---|
CTaskVehicleFSM < CTaskFSMClone @141 | 上下车类任务的公共基(门/座位保留、片段集请求等)game/task/Vehicle/TaskVehicleBase.h:141 |
CTaskEnterVehicle 及子任务 CTaskEnterVehicleAlign、CTaskOpenVehicleDoorFromOutside、CTaskEnterVehicleSeat、CTaskCloseVehicleDoorFromInside、CTaskInVehicleSeatShuffle | 上车(§3.3) |
CTaskExitVehicle 及 CTaskOpenVehicleDoorFromInside、CTaskExitVehicleSeat、CTaskCloseVehicleDoorFromOutside、CTaskReactToBeingJacked、CTaskReactToBeingAskedToLeaveVehicle | 下车与被劫 game/task/Vehicle/TaskExitVehicle.h:33-1278 |
CTaskGoToCarDoorAndStandStill、CTaskMoveGoToVehicleDoor | 走到车门 game/task/Vehicle/TaskGoToVehicleDoor.h:30-142 |
CTaskControlVehicle、CTaskCarDrive(Wander)、CTaskPlayerDrive、CTaskInVehicleBasic、CTaskLeaveAnyCar、CTaskComplexCarDriveUsingNavMesh… | 行人侧驾驶控制(把 VehicleAI 驾驶任务交给载具任务树)game/task/Vehicle/TaskCar.h:41-943 |
CTaskVehicleMountedWeapon、CTaskVehicleGun、CTaskVehicleProjectile | 车载武器/车内射击 |
CTaskMountAnimal/DismountAnimal/RideHorse/MotionRideHorse/PlayerOnHorse/MoveDraftAnimal… | 骑乘(多数受 ENABLE_HORSE 宏控制,属继承自早期项目的代码) |
CTaskRideTrain、CTaskGetOnTrain/OffTrain | 乘坐火车 |
CVehicleHullAI、CFollowNearestPathHelper、TaskCarUtils | 车辆船体避让、跟随最近路径辅助 |
2.9 Physics(NM 布娃娃)#
CTaskNMControl < CTaskFSMClone @1203 是 NM 行为的控制/起身容器,CTaskNMBehaviour < CTaskFSMClone @458 是各 NM 行为的基类(TaskNM.h)game/task/Physics/TaskNM.h:458、TaskNM.h:1203。派生行为约 25 个:Balance、Brace、Shot(3.5k 行)、HighFall、Explosion、OnFire、Electrocute、Flinch、Relax/RollUpAndRelax、InjuredOnGround、JumpRollFromRoadVehicle、ThroughWindscreen、RiverRapids、Buoyancy、Dangle、Drunk、Sit、SlungOverShoulder、DraggingToSafety、ScriptControl、Simple、Pose、Prototype、FallDown、GenericAttach、BindPose(__DEV)。辅助:CTaskBlendFromNM(从布娃娃混回动画并选择起身集 BlendFromNmData.psc)、CTaskRageRagdoll(非 NM 的 RAGE 布娃娃)、CTaskAnimatedAttach、CGrabHelper、CAnimPoseHelper、ThreatenedHelper。布娃娃任务类型集中在 TASK_NM_RELAX…TASK_RAGDOLL_LAST 区间(见 task-system §8.1)。NM 行为与物理世界的接口见 game-physics-and-ragdoll。
2.10 Weapons(武器)#
| 类 < 基类 | 职责 |
|---|---|
CTaskWeapon、CTaskPlayerWeapon | 武器行为的通用根(行人/玩家)game/task/Weapons/TaskWeapon.h:13 |
CTaskGun < CTaskFSMClone @26 | 枪械总控:Decide → AimIntro → Aim → Reload/Swap/BulletReaction → Quit game/task/Weapons/Gun/TaskGun.h:35-41 |
CTaskAimGun → CTaskAimGunOnFoot、CTaskAimGunVehicleDriveBy、CTaskAimGunScripted、CTaskAimGunBlindFire、CTaskMountThrowProjectile | 具体瞄准实现,由 CTaskAimGunFactory::CreateTask(type, …) 按任务类型 switch 创建 game/task/Weapons/Gun/TaskAimGunFactory.cpp:19-49 |
CTaskReloadGun、CTaskSwapWeapon、CTaskWeaponBlocked、CTaskAimSweep | 装弹、换武器、武器被阻挡 |
CTaskAimAndThrowProjectile、CTaskThrowProjectile、CTaskBomb、CTaskDetonator | 投掷物与炸弹 |
CWeaponController(Fixed/Player)、CWeaponTarget < CAITarget | 射击控制源(AI 固定/玩家输入)与目标描述 game/task/Weapons/WeaponController.h:57-79、game/task/Weapons/WeaponTarget.h:11 |
ScriptedGunTaskInfo(MetadataMgr) | 脚本枪械任务的元数据 |
2.11 Service、Crimes、Animation、Helpers、Debug#
- Service:
CTaskPolice/CTaskPoliceOrderResponse/CTaskPoliceWantedResponse/CTaskArrestPed(2)/CTaskBustedgame/task/Service/Police/TaskPolicePatrol.h:50-792;CTaskSwat及…OrderResponse/FollowInLine/GoToStagingArea/WantedResponse、CTaskHeliOrderResponsegame/task/Service/Swat/TaskSwat.h:28-422;CTaskFirePatrol、CTaskAmbulancePatrol、CTaskArmy、CTaskWitness。这些任务接收派遣系统的命令(CPoliceOrder等),派遣逻辑见 wanted-crime-dispatch。 - Crimes:
CRandomEventManager(随机事件计时、生成警车追逐等,参数来自元数据)game/task/Crimes/RandomEventManager.h:65-129、CDefaultCrimeInfo/CStealVehicleCrime、CTaskStealVehicle、CTaskPursueCriminal、CTaskReactToPursuit。 - Animation:
CTaskScriptedAnimation(脚本动画多优先级片段)、CTaskSynchronizedScene(同步场景)、CTaskCutScene、CTaskMoVEScripted(脚本驱动的 MoVE 网络)、CTaskClip/CTaskRunClip/CTaskRunNamedClip、CTaskReachArm、调试用CTaskPreviewMoveNetwork/CTaskTestMoveNetwork(BANK)game/task/Animation/TaskAnims.h:35-1126;动画系统本身见 game-animation-and-ik。 - Helpers:
CTaskConversationHelper : CTaskHelperFSM(环境对话)、CPropManagementHelper(场景/环境道具的生成、附着与释放)、PavementFloodFillHelpergame/task/Helpers/TaskConversationHelper.h:9。 - Debug:仅
CTaskTestClipDistancegame/task/Debug/TaskDebug.h:12。
2.12 Scenario(场景)#
见 §3.5。
3. 核心任务的状态机#
3.1 战斗:CTaskThreatResponse → CTaskCombat#
入口:可编辑事件经决策制定器选出 TASK_COMBAT/TASK_THREAT_RESPONSE/TASK_SMART_FLEE 后,由响应工厂创建 CTaskThreatResponse(逃跑时带覆盖)(见事件页 §7.3)。威胁响应在 Analysis 状态中调用 DetermineThreatResponseState:覆盖值 → 规则(ChooseThreatResponseFromRules)→ 战斗行为 → 属性 → 性格 → 兜底,任一环节得出结论即返回 game/task/Combat/TaskThreatResponse.cpp:647-720。战斗分支创建 CTaskCombat(target, 0, flags) TaskThreatResponse.cpp:1256。
状态(CTaskCombat::CombatState)game/task/Combat/TaskNewCombat.h:132-172:Start, Resume, Fire, InCover, MoveToCover, Retreat, Advance, AdvanceFrustrated, ChaseOnFoot, ChargeTarget, Flank, MeleeAttack, MoveWithinAttackWindow, MoveWithinDefensiveArea, PersueInVehicle, WaitingForEntryPointToBeClear, GoToEntryPoint, PullTargetFromVehicle, EnterVehicle, Search, DecideTargetLossResponse, DragInjuredToSafety, Mounted, MeleeToArmed, ReactToImminentExplosion, ReactToExplosion, ReactToBuddyShot, GetOutOfWater, WaitingForCoverExit, AimIntro, TargetUnreachable, ArrestTarget, MoveToTacticalPoint, ThrowSmokeGrenade, Victory, ReturnToInitialPosition, Finish。
状态→子任务(*_OnEnter 中的 SetNewTask):
| 状态 | 子任务 | 证据 |
|---|---|---|
Fire | CTaskShootAtTarget | TaskNewCombat.cpp:3046-3049 |
InCover / MoveToCover | CTaskCover | TaskNewCombat.cpp:3202-3220、TaskNewCombat.cpp:3659-3704 |
Retreat | CTaskCombatSeekCover | TaskNewCombat.cpp:3816-3822 |
MeleeAttack | CTaskMelee | TaskNewCombat.cpp:3836-3864 |
Advance | CTaskAdvance | TaskNewCombat.cpp:3948-3964 |
ChargeTarget | CTaskCharge | TaskNewCombat.cpp:4049-4108 |
ChaseOnFoot | CTaskComplexControlMovement(移动任务, CTaskCombatAdditionalTask) | TaskNewCombat.cpp:4163-4216 |
Flank | CTaskCombatFlank | TaskNewCombat.cpp:4348-4350 |
MoveWithinAttackWindow / MoveWithinDefensiveArea | 同名移动任务 | TaskNewCombat.cpp:4376-4388、TaskNewCombat.cpp:4516-4525 |
PersueInVehicle | CTaskVehiclePersuit | TaskNewCombat.cpp:4577-4593 |
PullTargetFromVehicle / EnterVehicle | CTaskEnterVehicle | TaskNewCombat.cpp:4983-5006、TaskNewCombat.cpp:5135-5181 |
Search | CTaskSearch | TaskNewCombat.cpp:5247-5254 |
DragInjuredToSafety | CTaskDraggingToSafety | TaskNewCombat.cpp:5333-5348 |
Mounted | CTaskCombatMounted | TaskNewCombat.cpp:5374-5376 |
ArrestTarget | CTaskArrestPed | TaskNewCombat.cpp:5653-5659 |
MoveToTacticalPoint | CTaskMoveToTacticalPoint | TaskNewCombat.cpp:5691-5700 |
TargetUnreachable | CTaskTargetUnreachable | TaskNewCombat.cpp:3569-3572 |
ReturnToInitialPosition | CTaskComplexControlMovement(移动, CTaskWeaponBlocked) | TaskNewCombat.cpp:5844-5855 |
决策方式:状态转移主要由 §task-system 2.5 的转移表驱动。条件位 ConditionFlags(如 CF_LosClear、CF_WillUseCover、CF_HasDesiredCover、CF_TargetLocationLost、CF_InVehicle、CF_CanArrestTarget,以及超出 32 位的 CF_CanMoveWithinDefensiveArea 等 64 位宏)由 GenerateTransitionConditionFlags 每次生成 TaskNewCombat.h:44-82、TaskNewCombat.cpp:1542。表的选择依据 CCombatBehaviour::GetCombatType:CT_OnFootArmed、CT_OnFootArmedSeekCoverOnly、CT_OnFootUnarmed、CT_Underwater 对应四张静态表 TaskNewCombat.cpp:671-683、game/Peds/CombatBehaviour.h:104-112。表内容例如“持械 Start 状态:有理想掩体→MoveToCover(权重 9)、视线清楚→Fire(1)、在车内→PersueInVehicle、骑乘→Mounted、可劫车→等待入口、可逮捕→ArrestTarget” TaskNewCombat.cpp:12651-12659;徒手表以近战为主 TaskNewCombat.cpp:12609-12639。各状态 OnUpdate 用 PeriodicallyCheckForStateTransitions(ScaleReactionTime(...)) 周期查表、在子任务结束时用 PickNewStateTransition(..., true)。ScaleReactionTime 忽略传入的 AVERAGE_STATE_SEARCH_TIME = 2.0f,直接按战斗能力返回 {5.0, 2.5, 1.0} 秒(CA_Poor/Average/Professional)TaskNewCombat.cpp:669、TaskNewCombat.cpp:686、TaskNewCombat.cpp:2112-2117、game/Peds/CombatData.psc:12-16。
退出条件:ProcessPreFSM 在目标无法更新/丢失、目标友好、不能攻击、目标已无通缉等情况下 FSM_Quit;若在车内、没有威胁响应父任务且被要求“总是逃跑”,则通过 CEventGivePedTask 给自己一个 CTaskThreatResponse 后退出 TaskNewCombat.cpp:1104-1145。克隆端有单独的 ProcessPreFSM_Clone 与 UpdateClonedFSM TaskNewCombat.cpp:1519、TaskNewCombat.cpp:2427。调优数据 CTaskCombat::Tunables 在 Combat/Metadata.psc game/task/Combat/Metadata.psc:950。
图为简化示意:从 Start 出发的边来自持械/徒手转移表 TaskNewCombat.cpp:12612-12659;InCover/Fire/Search 之间的边为示意性(完整边集需阅读 COnFootArmedTransitions::Init 全部条目 TaskNewCombat.cpp:12651 之后),Finish 来自各处 PickNewStateTransition(State_Finish) TaskNewCombat.cpp:3152。
3.2 导航:CTaskNavBase / CTaskMoveFollowNavMesh#
CTaskNavBase 是所有“请求 pathserver 路线并沿路线移动”的移动任务基类,CTaskMoveFollowNavMesh(TASK_MOVE_FOLLOW_NAVMESH)与 CTaskMoveWander 继承它。路线 CNavMeshRoute 最多 16 个路点(与 pathserver 返回的 MAX_NUM_PATH_POINTS = 16 一致)game/task/Movement/TaskNavBase.h:51-78。
状态 TaskNavBase.h:545-563:Initial, WaitingInVehiclePriorToRequest, RequestPath, MovingWhilstWaitingForPath, StationaryWhilstWaitingForPath, WaitingToLeaveVehicle, WaitingAfterFailureToObtainPath, FollowingPath, SlideToCoord, StoppingAtTarget, WaitingForWaypointActionEvent, WaitingAfterFailedWaypointAction, GetOntoMainNavMesh, AchieveHeading, UsingLadder;CTaskMoveFollowNavMesh 追加 WaitingBetweenSearchAttempts, WaitingBetweenRepeatSearches, SlidingToCoord, GetOntoMainNavMesh, AttemptTeleportToLeader game/task/Movement/TaskNavMesh.h:237-241。
证据与要点:
Initial依据是否需要先在车里等待选择下一状态,并初始化前瞻距离与最大可行坡度game/task/Movement/TaskNavBase.cpp:1171-1195。RequestPath_OnEnter:首次运行时若站在带动态导航网格的载具上,则把目标转到载具局部空间以便随车移动;然后RequestPath()TaskNavBase.cpp:1260-1333。RequestPath用InitPathRequestPathStruct填TRequestPathStruct、按行人 LOD 修改路径标志,再调用CPathServer::RequestPath;句柄为PATH_HANDLE_NULL(请求槽满)时走失败等待TaskNavBase.cpp:3918-3964。RequestPath_OnUpdate选择“边等边走”(ShouldKeepMovingWhilstWaitingForPath)或原地等待TaskNavBase.cpp:1334-1372。原地等待时每帧轮询CPathServer::IsRequestResultReady;就绪后RetrievePath通过LockPathResult拷出路点与标志(是否以目标结束、是否含水域等),成功进入FollowingPath,失败交给OnFailedRouteTaskNavBase.cpp:1545-1620、TaskNavBase.cpp:4008-4060。FollowingPath_OnEnter创建路线跟随子任务(若路线含攀爬/下落路点则以CTaskMoveGoToPointAndStandStill在路点前停下),并预先流送梯子片段TaskNavBase.cpp:1648-1697、TaskNavBase.cpp:4259-4330。FollowingPath_OnUpdate:按CalcScanForObstructionsFreq周期前向扫描障碍,发现障碍则从障碍前方重新请求路线TaskNavBase.cpp:2198-2250;路线不以目标结束(pathserver 只返回有限路点)且剩余距离 <ms_fDistanceFromRouteEndToRequestNextSection(默认 6 m)时,以“前方一段距离”为起点在跟随中预请求下一段(NB_CalculatingPathOnTheFly)TaskNavBase.cpp:2890-2907、TaskNavBase.cpp:571、TaskNavBase.cpp:3966-4006;到达特殊路点时进入WaitingForWaypointActionEvent,并向自身添加CEventClimbLadderOnRoute/CEventClimbNavMeshOnRoute,由事件处理器在主树临时槽插入CTaskUseLadderOnRoute/CTaskUseClimbOnRoute/CTaskUseDropDownOnRouteTaskNavBase.cpp:3424-3425、TaskNavBase.cpp:3506-3518、game/event/EventMovement.cpp:66-79。- 主线程在 pathserver 处理前会用行人的
CNavMeshTrackedObject刷新尚未开始处理的请求起点(KEEP_UPDATING_PED_START_POSITION),并在请求完成时为等待中的行人置WaitingForCompletedPathRequest复位标志以取消 AI 时间切片(见导航页 §4.4)。
3.3 上车:CTaskEnterVehicle#
状态由 ENTER_VEHICLE_STATES(X) 列出 38 个 game/task/Vehicle/TaskEnterVehicle.h:313-356。主线路径(其余为分支:摩托扶车、攀爬/翻越上车顶、等待组长、等待网络同步、布娃娃等):
证据:各 *_OnUpdate 中的 SetTaskState(State_X) 调用(例如 PickDoor_OnUpdate 起于 TaskEnterVehicle.cpp:3009,EnterSeat_OnUpdate 在子任务完成后进入 WaitForPedToLeaveSeat TaskEnterVehicle.cpp:7408-7421,SetPedInSeat_OnUpdate 计算 iDesiredState 后切换 TaskEnterVehicle.cpp:8560-8790)。子任务:GoToDoor→CTaskGoToCarDoorAndStandStill TaskEnterVehicle.cpp:3691;Align→CTaskEnterVehicleAlign TaskEnterVehicle.cpp:10308;OpenDoor→CTaskOpenVehicleDoorFromOutside TaskEnterVehicle.cpp:5852;EnterSeat→CTaskEnterVehicleSeat TaskEnterVehicle.cpp:7279;CloseDoor→CTaskCloseVehicleDoorFromInside TaskEnterVehicle.cpp:8888;ShuffleToSeat→CTaskInVehicleSeatShuffle TaskEnterVehicle.cpp:10683;TryToGrabVehicleDoor→CTaskTryToGrabVehicleDoor TaskEnterVehicle.cpp:10758。
关键机制:
- 组件保留:门与座位用
CComponentReservation保留/释放(ReserveSeat/ReserveDoorToOpen/ReserveDoorToClose/UnReserve*状态),避免多人同时操作同一门/座(类前向声明TaskEnterVehicle.h:25)。 - 劫车是跨行人协作:
JackPedFromOutside_OnEnter通过CEventGivePedTask(PED_TASK_PRIORITY_EVENT_RESPONSE_TEMP, CTaskExitVehicle(...))让车内的人执行被拖出动作TaskEnterVehicle.cpp:6832-6900。 - 共享 MoVE 网络:主任务持有
m_moveNetworkHelper并传给开门/入座/关门/换座子任务,使整个上车过程在一个动画网络内连续过渡(见上面子任务构造参数)。 - 超时保护:入座状态超过
MAX_TIME_TO_GET_IN = 8 s断言并回退TaskEnterVehicle.cpp:7381-7395;入座退出时若载具对该玩家上锁则立即给退出任务TaskEnterVehicle.cpp:7425-7437。 - 网络:作为
CTaskVehicleFSM(CTaskFSMClone)派生类,克隆端根据GetStateFromNetwork()与查询接口推进(如换座时等待远端换座任务进入特定状态)TaskEnterVehicle.cpp:8746-8776。
3.4 动作树:CTaskMotionPed / CTaskHumanLocomotion#
- 选择:
CPed::ComputePrimaryMotionTask依据模型的CMotionTaskDataSet(peds.meta引用,结构见MotionTaskData.psc)选择:骑乘→CTaskMotionRideHorse;游泳且有水中数据→水中类型;否则用步行数据game/Peds/Ped.cpp:875-907、game/task/System/MotionTaskData.psc:4-74。人类(PED_ON_FOOT/PED_IN_WATER)一律使用CTaskMotionPed,低 LOD 时用CTaskMotionPedLowLod,两者互换时复制片段集与备用片段并以 0.25 s 插入混合Ped.cpp:909-972。动物类型(鸟、鱼、马、四足…)选择对应运动任务(同一 switch 的其余分支)。 CTaskMotionPed状态game/task/Motion/Locomotion/TaskMotionPed.h:34-57:Start, OnFoot, Strafing, StrafeToOnFoot, Swimming, SwimToRun, DiveToSwim, Diving, DoNothing, AnimatedVelocity, Crouch, Stealth, InVehicle, Aiming, StandToCrouch, CrouchToStand, ActionMode, Parachuting, Jetpack, Drunk, Dead, Exit(部分受宏控制)。各状态的子任务:OnFoot/ActionMode/Crouch/Stealth→CTaskHumanLocomotion(不同片段集)TaskMotionPed.cpp:1510-1519、TaskMotionPed.cpp:2796、TaskMotionPed.cpp:5884;Strafing→CTaskMotionStrafingTaskMotionPed.cpp:3351;Swimming→CTaskMotionSwimmingTaskMotionPed.cpp:3656;Diving→CTaskMotionDivingTaskMotionPed.cpp:4079;InVehicle→CTaskMotionInVehicleTaskMotionPed.cpp:4410;Aiming→CTaskMotionAimingTaskMotionPed.cpp:4768;Parachuting/Jetpack/Drunk→对应动作任务TaskMotionPed.cpp:5549-5657。- MoVE 网络嵌套:
CTaskMotionPed创建ms_NetworkMotionPed网络玩家TaskMotionPed.cpp:712;进入OnFoot时向父网络发送OnFoot请求,并让子任务网络SetupDeferredInsert到父网络的OnFootNetwork槽TaskMotionPed.cpp:1517-1519。也就是说,动作树任务链与 MoVE 网络树一一嵌套,状态切换=网络请求+子网络插入。 - 输入:期望移动混合比由移动树写入
CPedMotionData,CTaskMotionPed读取TaskMotionPed.cpp:830;网络玩家克隆从同步数据读取TaskMotionPed.cpp:2289。 CTaskHumanLocomotion状态game/task/Motion/Locomotion/TaskHumanLocomotion.h:98-110:Initial, Idle, IdleTurn, Start, Moving, Turn180, Stop, RepositionMove, FromStrafe, CustomIdle——起步/行进/急转/停步/原地调整,对应 MoVE 运动网络中的子状态(动画参数细节见动画页)。- 游戏性参数:动作任务数据集给出步行/跑/冲刺转向速率、跳跃/坠落/滑坡/游泳片段集、四足步态切换时间等
MotionTaskData.psc:27-61;Motion/Metadata.psc存放动作任务的Tunables。
3.5 场景系统:CScenarioPointManager / CScenarioInfoManager / CScenarioManager / CTaskUseScenario#
场景(scenario)= 世界中可供行人/载具“使用”的点(坐长椅、抽烟、站岗、加油站洗车…),是城市氛围的主要来源。
- 数据:
CScenarioPointManager读取场景点清单(CScenarioPointManifest:区域定义、点组、内部名表),每个区域定义CScenarioPointRegionDef{名称, AABB}通过g_fwMetaDataStore.MakeSlotStreamable(name, AABB)注册为按包围盒流送的元数据槽game/task/Scenario/ScenarioPointManager.h:43-80、game/task/Scenario/ScenarioPointManager.cpp:788-796;清单为 PSO,注册SCENARIO_POINTS_PSO_FILE/SCENARIO_POINTS_OVERRIDE_PSO_FILE两种数据文件挂载(DLC 追加/覆盖)ScenarioPointManager.cpp:156-157、ScenarioPointManager.cpp:1037-1048;-notscenariopointsstreaming参数可关闭流送ScenarioPointManager.cpp:50。schema 见ScenarioPointManager.psc:4-188(区域、簇、点、链节点/边/图、点组)。场景类型与模型集各占 9 位(各最多 512 种)game/task/Scenario/ScenarioPoint.h:36-44。CScenarioInfoManager从commoncrc:/data/ai/scenarios.meta及 DLC 的SCENARIO_INFO(_OVERRIDE)_FILE加载场景类型game/task/Scenario/info/ScenarioInfoManager.cpp:35-80、ScenarioInfoManager.cpp:488;CScenarioInfo子类决定任务类型:PlayAnims、Wandering、WanderingInRadius、Group、Couple、ControlAmbient、Skiing、SkiLift、MoveBetween、Sniper、Jogging、ParkedVehicle、Vehicle/VehiclePark、Flee、LookAt、DeadPedgame/task/Scenario/info/ScenarioInfo.h:338-703;条件系统CScenarioCondition*(约 70 种:天气、时间、模型、性别、持枪、在车内、电台音乐…)info/ScenarioInfoConditions.h:72-1198;场景中受事件打断时的行为由CScenarioAction*+CScenarioActionCondition*数据描述(立即退出、正常退出后响应、懦弱退出、逃跑、转头…)info/ScenarioAction.h:17-251。- 条件动画
common:/data/ai/conditionalanims.meta与环境模型集在game/ai/ambient中(见导航页 game/ai 盘点)game/ai/ambient/ConditionalAnimManager.cpp:142-152。
- 调度:
CScenarioManager::Update每帧更新条件、流送压力、链测试、生成检查缓存、生成历史、链使用信息、簇(SCENARIOCLUSTERING)、实体覆盖、车辆生成器与非区域点空间数组game/task/Scenario/ScenarioManager.cpp:569-631;刷人入口GiveScenarioToScenarioPoint/CreateScenarioPed/SetupScenarioAndTask,给停车/行驶车辆分配场景GiveScenarioToParkedCar/DrivingCargame/task/Scenario/ScenarioManager.h:248-299。脚本可抑制场景退出/吸引/突发退出ScenarioManager.h:202-213。初始化通过 gameSkeleton 注册game/Core/game.cpp:2130、game.cpp:2301。 - 任务工厂:
CScenarioManager::CreateTask(point, scenario)按CScenarioInfo子类创建:Flee→CTaskUseScenario(SF_StartInCurrentPosition|SF_SkipEnterClip);WanderingInRadius→CTaskWanderingInRadiusScenario;PlayAnims→CTaskUseScenario(环境用途加SF_FlagsForAmbientUsage,联机加SF_AddToHistory);MoveBetween→CTaskMoveBetweenPointsScenario;Jogging/Wandering→CTaskWanderingScenario;DeadPed→CTaskDeadBodyScenario;其他断言ScenarioManager.cpp:5431-5488;生成的场景任务可再被CTaskUnalerted包装以支持场景链与闲逛ScenarioManager.cpp:5179。 CTaskUseScenario状态game/task/Scenario/Types/TaskUseScenario.h:298-317:Start → GoToStartPosition(CTaskGoToScenario)→ Enter(入场片段)→ PlayAmbients(CTaskAmbientClips 播放条件动画/道具)→ Exit / PanicExit / NMExit / PanicNMExit / AggroOrCowardIntro/Outro / ScenarioTransition → Finish,外加WaitingOnExit/StreamWaitClip/WaitForProbes/WaitForPath等异步等待状态TaskUseScenario.cpp:3365-3427、TaskUseScenario.cpp:4070-4108。中止后默认从Start恢复TaskUseScenario.h:347。- 其他场景模块:
ScenarioChaining(场景链图与使用者跟踪)、ScenarioClustering(簇一次性生成)、ScenarioSpawnHistory、ScenarioVehicleManager、ScenarioEntityOverride、ScenarioFinder(CTaskHelperFSM)、ScenarioEditor/ScenarioDebug/ScenarioAnimDebugHelper(BANK 编辑器与调试)。
约束与边界行为#
- 新任务的“注册清单”:新增一个任务通常要同时改
TaskTypes.h(类型)、TaskClassInfo.cpp(T2N)、可能的Metadata.psc(Tunables)、若需联网还要在CQueriableInterface::CreateEmptyTaskInfo/IsTaskSentOverNetwork中登记(game/Peds/QueriableInterface.cpp:927、QueriableInterface.cpp:1839),若作为事件响应还要在CEventResponseFactory或FindTaskTypeForResponse中登记。遗漏任一处只会在断言版暴露。 - 任务大小:所有任务共享一个固定槽大小的池,大型任务(掩体、上车、战斗)要注意
GetLargestTaskSize的断言阈值(见 task-system §7.1)。 - 宏控制的“死代码”:骑马(
ENABLE_HORSE)、手铐/羁押(ENABLE_TASKS_ARREST_CUFFED)、CnC 模式(CNC_MODE_ENABLED)相关任务是否参与编译取决于宏;本页未逐一核对这些宏在各构建中的取值。
未决问题 / 证据不足#
- 本页对
Combat、Movement、Vehicle中约 200 个任务只给出族谱级描述;CTaskCover(约 3 万行)、CTaskMelee、CTaskParachute、CTaskInVehicle的内部状态机未展开。 CTaskCombat转移表的完整边集未逐条列出(图为简化示意)。- 场景刷人与人口系统的配额/距离参数属于 06-peds 页范围,本页未深入。