# Skill Learn Flow (C++) 1. **CDlgSkillSubListItem::OnCommand_Upgrade** - Triggered when the player clicks the learn/upgrade button on a skill. - Performs status checks (dead, trading, etc.), evaluates `CheckLearnCondition`, and shows the `Game_LearnSkill` confirmation dialog. - If the NPC greeting has not been received yet, calls `CECHostSkillModel::SendHelloToSkillLearnNPC()`. 2. **CECHostSkillModel** - Maintains `m_skillLearnNPCNID`, the NPC ID that currently offers skill learning. - `ProcessServiceList()` scans `cmd_scene_service_npc_list` from the server, keeps the valid NPC, and resets `m_bReceivedNPCGreeting` when a new NPC is selected. - `SendHelloToSkillLearnNPC()` issues `c2s_CmdNPCSevHello(m_skillLearnNPCNID)` to start the NPC service handshake. - `OnNpcGreeting()` is invoked when `NPC_GREETING` (cmd 70) arrives; it marks the greeting as received so future learns skip re-hello. 3. **CDlgSkillAction::TryOpenDialog** - Called when the skill dialog is being opened (skill vs action mode). - If the host isn’t currently “talking with the NPC,” it forces the dialog to open, sends `SendHelloToSkillLearnNPC()`, and clears the “received greeting” flag so the next dialog confirms again. 4. **Game UI dialog** - Player confirms the `Game_LearnSkill` message box (`EC_GameUIMan::OnMessageBoxClose`). - If `IDOK` and `CheckSkillLearnCondition` still returns zero, it sends `c2s_CmdNPCSevLearnSkill(skillID)`. - The dialog name `"Game_LearnSkill"` ensures the server hasn’t rejected the skill because it missed the handshake. 5. **Server round-trip** - `SEVNPC_HELLO` establishes the NPC service context. - Server replies with `NPC_GREETING`, parsed by `GameSession` and forwarded to `CECHostSkillModel::OnNpcGreeting`. - Only after the greeting can `SEVNPC_SERVE` with `GP_NPCSEV_LEARN` be trusted; else, the server often drops it without a `LEARN_SKILL` response. Use this sequence when troubleshooting missing `LEARN_SKILL` responses: show/confirm dialog → send `SEVNPC_HELLO` → wait for `NPC_GREETING` → send `GP_NPCSEV_LEARN`.