6.7 KiB
Comparison: OnMsgPlayerCastSkill - C++ vs C# Conversion
Summary
The conversion from C++ to C# is mostly complete but has some missing elements and commented-out code that should be reviewed.
All Switch Cases Present ✅
All 9 switch cases are present in both versions:
- ✅
OBJECT_CAST_SKILL - ✅
SKILL_PERFORM - ✅
HOST_STOP_SKILL - ✅
SELF_SKILL_INTERRUPTED - ✅
OBJECT_CAST_INSTANT_SKILL - ✅
OBJECT_CAST_POS_SKILL - ✅
PLAYER_CAST_RUNE_SKILL - ✅
PLAYER_CAST_RUNE_INSTANT_SKILL - ✅
ERROR_MESSAGE - ✅
defaultcase
Missing/Incomplete Elements
1. Missing Assertion Check in OBJECT_CAST_SKILL ❌
C++ (line 5876):
ASSERT(pCmd->caster == m_PlayerInfo.cid);
C# (line 916):
// MISSING: No assertion check for pCmd.caster == m_PlayerInfo.cid
Impact: Medium - This is a safety check that validates the caster ID matches the player's ID.
2. Commented Out AP_ActionEvent in HOST_STOP_SKILL ⚠️
C++ (line 5958):
AP_ActionEvent(AP_EVENT_STOPSKILL);
C# (line 1025):
//AP_ActionEvent(AP_EVENT_STOPSKILL);
Impact: Medium - Action event notification is disabled. May affect auto-policy or other systems that listen to this event.
3. Commented Out AP_ActionEvent in SELF_SKILL_INTERRUPTED ⚠️
C++ (line 6005):
AP_ActionEvent(AP_EVENT_STOPSKILL);
C# (line 1084):
//AP_ActionEvent(AP_EVENT_STOPSKILL);
Impact: Medium - Same as above.
4. Missing Fixed Message in SELF_SKILL_INTERRUPTED ⚠️
C++ (line 6003):
g_pGame->GetGameRun()->AddFixedMessage(FIXMSG_SKILLINTERRUPT);
C# (line 1081):
// g_pGame.GetGameRun().AddFixedMessage(FIXMSG_SKILLINTERRUPT);
Debug.Log("Skill interrupted!");
Impact: Low - Replaced with Debug.Log, but the fixed message system might be needed for UI notifications.
5. Missing Auto-Policy Event in SELF_SKILL_INTERRUPTED ⚠️
C++ (line 6008):
CECAutoPolicy::GetInstance().SendEvent_SkillInterrupt(skill_id);
C# (line 1087):
// CECAutoPolicy::GetInstance().SendEvent_SkillInterrupt(skill_id);
Impact: Medium - Auto-policy system won't be notified of skill interruptions, which may affect automated gameplay features.
6. Commented Out Camera Update in OBJECT_CAST_POS_SKILL ⚠️
C++ (line 6080):
UpdateFollowCamera(false, 10);
C# (line 1165):
//UpdateFollowCamera(false, 10);
Impact: Low - Camera update is disabled. May affect camera behavior for certain skills.
Differences That Are Acceptable
1. Logging System Differences ✅
C++:
g_pGame->RuntimeDebugInfo(0xffffffff, _AL("Cast skill(%d): %s"), ...);
C#:
Debug.Log($"Cast skill({m_pCurSkill.GetSkillID()})");
Status: Acceptable - Different logging systems, functionality preserved.
2. Additional Logging in C# ✅
C# has extra logging for return-to-town skill (ID 167):
if (m_pCurSkill.GetSkillID() == ID_RETURNTOWN_SKILL)
{
Debug.Log($"Return-to-town skill (167) cast - State2 should trigger SetReturntown(1) on server");
}
Status: Acceptable - Additional debugging/logging is fine.
3. Memory Management Differences ✅
C++:
if(m_pTargetItemSkill)
{
delete m_pTargetItemSkill;
m_pTargetItemSkill = NULL;
}
C#:
if (m_pTargetItemSkill != null)
{
m_pTargetItemSkill = null; // GC will handle cleanup
}
Status: Acceptable - C# uses garbage collection, no explicit delete needed.
4. Type Casting Differences ✅
C++:
cmd_object_cast_skill* pCmd = (cmd_object_cast_skill*)Msg.dwParam1;
C#:
cmd_object_cast_skill pCmd = GPDataTypeHelper.FromBytes<cmd_object_cast_skill>((byte[])Msg.dwParam1);
Status: Acceptable - Different serialization approach, functionality preserved.
5. Switch Statement Syntax ✅
C++:
switch (Msg.dwParam2)
{
case OBJECT_CAST_SKILL:
C#:
switch (Convert.ToInt32(Msg.dwParam2))
{
case int value2 when value2 == CommandID.OBJECT_CAST_SKILL:
Status: Acceptable - C# pattern matching syntax, functionality preserved.
Post-Switch Code Comparison
Action Start Event ✅
C++ (line 6241-6242):
if( bActionStartSkill )
AP_ActionEvent(AP_EVENT_STARTSKILL, iActionTime);
C# (line 1338-1339):
if (bActionStartSkill)
AP.AP_ActionEvent((int)AP_EVENT.AP_EVENT_STARTSKILL, iActionTime);
Status: ✅ Complete - Properly converted and active.
Do Other Thing Logic ✅
C++ (line 6244-6258):
if (bDoOtherThing)
{
if (m_pComboSkill && !m_pComboSkill->IsStop())
{
if( CECAutoPolicy::GetInstance().IsAutoPolicyEnabled() )
g_pGame->GetGameRun()->PostMessage(MSG_HST_CONTINUECOMBOSKILL, MAN_PLAYER, 0, 0, m_pComboSkill->GetGroupIndex());
else
m_pComboSkill->Continue(false);
}
else
{
if( idTarget && idTarget != m_PlayerInfo.cid )
NormalAttackObject(idTarget, true);
}
}
C# (line 1341-1357):
if (bDoOtherThing)
{
if (m_pComboSkill != null && !m_pComboSkill.IsStop())
{
if (CECAutoPolicy.GetInstance().IsAutoPolicyEnabled())
EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_CONTINUECOMBOSKILL, MANAGER_INDEX.MAN_PLAYER, 0, 0, m_pComboSkill.GetGroupIndex());
else
m_pComboSkill.Continue(false);
}
else
{
if (idTarget != 0 && idTarget != m_PlayerInfo.cid)
NormalAttackObject(idTarget, true);
}
}
Status: ✅ Complete - Properly converted with equivalent logic.
Recommendations
High Priority
- Add missing assertion check in
OBJECT_CAST_SKILLcase:Debug.Assert(pCmd.caster == m_PlayerInfo.cid, "Caster ID mismatch");
Medium Priority
- Uncomment and verify
AP_ActionEvent(AP_EVENT_STOPSKILL)calls if the AP system is implemented in C#. - Uncomment
CECAutoPolicy::GetInstance().SendEvent_SkillInterrupt(skill_id)if auto-policy is needed.
Low Priority
- Review if
UpdateFollowCamerais needed forOBJECT_CAST_POS_SKILLcase. - Consider implementing
AddFixedMessagesystem if UI notifications are needed for skill interruptions.
Conclusion
Conversion Completeness: ~90%
The conversion is functionally complete with all major logic paths implemented. However, several safety checks and event notifications are commented out or missing, which may affect:
- Auto-policy system integration
- UI notifications for skill interruptions
- Camera behavior for position-based skills
- Safety validation (caster ID check)
These should be reviewed and either implemented or confirmed as intentionally disabled.