# Flash Move Skill Protocol Comparison: C++ vs C# ## Summary **Both C++ and C# send the same command ID (89) for CAST_POS_SKILL**, but they use different protocol wrappers. ## C++ Implementation ### Log Evidence (EC.log) ``` [17:10:03.501] [FLASH_SKILL_PROTOCOL] c2s_SendCmdCastPosSkill: Sending protocol C2S::CAST_POS_SKILL (command ID=89), skillID=58, pos=(858.33, 60.93, -149.44), byPVPMask=0, targetCount=0 [17:10:03.501] [FLASH_SKILL_PROTOCOL] c2s_SendCmdCastPosSkill: Protocol packet size=20 bytes [17:10:03.501] CLIENT - CAST_POS_SKILL(89) ``` ### Code Location - **File:** `EC_SendC2SCmds.cpp` - **Function:** `c2s_SendCmdCastPosSkill()` (line 1030-1068) - **Protocol:** Sends `C2S::CAST_POS_SKILL` directly as protocol command - **Command ID:** 89 (from enum `C2S::CAST_POS_SKILL`) - **Packet Structure:** ```cpp [cmd_header] + [cmd_cast_pos_skill] - cmd_header.cmd = C2S::CAST_POS_SKILL (89) - cmd_cast_pos_skill contains: skill_id, pos, force_attack, target_count, targets[] ``` ## C# Implementation ### Log Evidence (SessionLog) ``` [16:58:15.286] [DISTANCE_DEBUG] CastSkill: Before sending c2s_CmdCastPosSkill (flashmove self), skillID=58, hostPos=(860.71, 59.59, -130.28), destPos=(860.62, 60.73, -145.39), flashDistance=16.00, byPVPMask=0 [16:58:15.286] [GameSession] Sending protocol: gamedatasend (Type: PROTOCOL_GAMEDATASEND) + Type=34 - CMD_ID: CAST_POS_SKILL ``` ### Code Location - **File:** `C2SCommand.cs` - **Enum:** `CommandID.CAST_POS_SKILL = 89` (line 118) - **Protocol:** Wraps command in `PROTOCOL_GAMEDATASEND` (Type=34) - **Command ID:** 89 (stored in first 2 bytes of Data field) - **Packet Structure:** ```csharp [PROTOCOL_GAMEDATASEND header] + [Data field] - Protocol Type = 34 (PROTOCOL_GAMEDATASEND) - Data[0-1] = CommandID.CAST_POS_SKILL (89) as ushort - Data[2+] = CMD_CastPosSkill structure (skillId, pos, pvpMask, targetCount, targets[]) ``` ## Key Differences | Aspect | C++ | C# | |--------|-----|-----| | **Protocol Type** | Direct command (89) | Wrapped in PROTOCOL_GAMEDATASEND (34) | | **Command ID** | 89 (C2S::CAST_POS_SKILL) | 89 (CommandID.CAST_POS_SKILL) | | **Packet Structure** | `[cmd_header][cmd_cast_pos_skill]` | `[PROTOCOL_GAMEDATASEND][Data with CMD_ID][CMD_CastPosSkill]` | | **Packet Size** | 20 bytes (for skillID=58, no targets) | Larger (includes PROTOCOL_GAMEDATASEND wrapper) | ## Conclusion ✅ **The command ID is the same (89)** in both implementations. ⚠️ **The protocol wrapper is different:** - **C++** sends the command directly as protocol 89 - **C#** wraps it in `PROTOCOL_GAMEDATASEND` (34) and puts the command ID (89) in the Data field This is a **protocol architecture difference**, not a bug. The C# implementation uses a unified `GameDataSend` protocol that wraps all game commands, while the C++ implementation sends commands directly. The server should handle both formats correctly if it recognizes: 1. Direct protocol 89 (C++ style) 2. Protocol 34 with command ID 89 in the data (C# style) ## Verification Both logs show: - **Skill ID:** 58 (same flash move skill) - **Command ID:** 89 (CAST_POS_SKILL) - **Position data:** Present in both - **PVP Mask:** 0 in both - **Target Count:** 0 in both The actual command data is **identical**; only the protocol wrapper differs.