{"record":{"id":"980f0dbf929455f5","repo":"babalae/better-genshin-impact","slug":"logicalslot-maxcontrolavat","errorCode":null,"errorMessage":"切换角色：{logicalSlot} 号位超出当前账号可操作角色数 {_maxControlAvatarCount}","messagePattern":"切换角色：(.+?) 号位超出当前账号可操作角色数 (.+?)","errorType":"exception","errorClass":"PartySetupFailedException","httpStatus":null,"severity":"error","filePath":"BetterGenshinImpact/GameTask/Common/Job/SwitchCharacterStateMachineTask.cs","lineNumber":1272,"sourceCode":"            (4, 4) => [4],\n            _ => throw new PartySetupFailedException(\n                $\"切换角色：无法为 {_multiGamePlayerCount} 人联机的 {_playerIndex}P 生成可控槽位\")\n        };\n\n        _maxControlAvatarCount = physicalSlots.Length;\n        _logicalToPhysicalSlot = physicalSlots\n            .Select((physical, index) => (Logical: index + 1, Physical: physical))\n            .ToDictionary(pair => pair.Logical, pair => pair.Physical);\n\n        _logger.LogInformation(\"切换角色：{PlayerCount} 人队伍，{PlayerIndex}P 可控物理槽位 {Slots}\",\n            _multiGamePlayerCount, _playerIndex, string.Join(\",\", physicalSlots));\n    }\n\n    private void EnsureSlotIsOperable(int logicalSlot)\n    {\n        if (!_logicalToPhysicalSlot.ContainsKey(logicalSlot))\n        {\n            throw new PartySetupFailedException($\"切换角色：{logicalSlot} 号位超出当前账号可操作角色数 {_maxControlAvatarCount}\");\n        }\n    }\n\n    private void AdjustTargetsToOperableSlots()\n    {\n        int[] ignoredSlots;\n        if (_usePhysicalSlots)\n        {\n            var logicalByPhysicalSlot = _logicalToPhysicalSlot\n                .ToDictionary(pair => pair.Value, pair => pair.Key);\n            ignoredSlots = _targetRoles\n                .Where(role => !logicalByPhysicalSlot.ContainsKey(role.Slot))\n                .Select(role => role.Slot)\n                .OrderBy(slot => slot)\n                .ToArray();\n\n            _targetRoles = _targetRoles\n                .Where(role => logicalByPhysicalSlot.ContainsKey(role.Slot))","sourceCodeStart":1254,"sourceCodeEnd":1290,"githubUrl":"https://github.com/babalae/better-genshin-impact/blob/a7cb36712dcb409be610257d877fcea3597e9d6b/BetterGenshinImpact/GameTask/Common/Job/SwitchCharacterStateMachineTask.cs#L1254-L1290","documentation":"EnsureSlotIsOperable checks that a logical slot exists in _logicalToPhysicalSlot (the controllable-slot map built by ConfigureOperableSlots). In co-op a player only owns some physical slots, so requesting a logical slot beyond _maxControlAvatarCount (e.g. 2P asking for logical slot 3) has no physical target and is rejected.","triggerScenarios":"EnsureSlotIsOperable(logicalSlot) is called (from ClickFixedTeamSlot or HandlePrepareNextRole) with a logicalSlot not present in _logicalToPhysicalSlot, which happens when the requested target role's slot exceeds the controllable count for this player in co-op.","commonSituations":"usePhysicalSlots=false and a target role references a slot index beyond _maxControlAvatarCount; usePhysicalSlots=true but AdjustTargetsToOperableSlots did not filter/remap it; a co-op player issued a 4-slot command but only controls 1-2 slots.","solutions":["Rely on AdjustTargetsToOperableSlots to strip/ignore slots the current player cannot operate before any click — confirm it ran and filtered the offending role.","When scripting for co-op, only request slots within the player's controllable range (documented in Start's remarks).","Call EnsureSlotIsOperable earlier (during BuildSwitchPlan) to fail with context before attempting UI clicks."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"if (!_logicalToPhysicalSlot.ContainsKey(role.Slot))\n{\n    _logger.LogWarning(\"切换角色：忽略不可操作槽位 {Slot}\", role.Slot);\n    continue;\n}","typeGuard":"bool IsOperable(int logicalSlot) => _logicalToPhysicalSlot.ContainsKey(logicalSlot);","tryCatchPattern":"try { await switchTask.Start(...); }\ncatch (PartySetupFailedException ex) when (ex.Message.Contains(\"超出当前账号可操作角色数\"))\n{ _logger.LogWarning(ex, \"联机模式下请求了不可控槽位，已忽略\"); }","preventionTips":["Let AdjustTargetsToOperableSlots strip inoperable slots before any click.","In co-op, request only slots within the player's controllable range.","Validate slot operability early in BuildSwitchPlan."],"tags":["party-setup","co-op","validation","slot-mapping","switch-character"],"backgroundTag":null,"analyzedSha":"a7cb36712dcb409be610257d877fcea3597e9d6b","analyzedAt":"2026-08-13T16:44:57.548Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}