Files
test/agent-skills/03-code-patterns.md
T
2026-02-24 09:50:08 +07:00

419 lines
8.6 KiB
Markdown

# Code Patterns - C++ to C# Conversions
## Abstract Base Classes
### C++ Pattern
```cpp
class CGfxMoveBase
{
protected:
CGfxMoveBase(GfxMoveMode mode) : m_Mode(mode) {}
public:
virtual ~CGfxMoveBase() {}
virtual void StartMove(const A3DVECTOR3& vHost, const A3DVECTOR3& vTarget) = 0;
virtual bool TickMove(DWORD dwDeltaTime, ...) = 0;
virtual void SetParam(const GFX_SKILL_PARAM* param) { /* default impl */ }
static CGfxMoveBase* CreateMoveMethod(GfxMoveMode mode);
};
```
### C# Pattern
```csharp
public abstract class CGfxMoveBase
{
protected CGfxMoveBase(GfxMoveMode mode)
{
m_Mode = mode;
}
// Pure virtual (= 0) → abstract
public abstract void StartMove(Vector3 vHost, Vector3 vTarget);
public abstract bool TickMove(uint dwDeltaTime, ...);
// Virtual with default → virtual
public virtual void SetParam(GFX_SKILL_PARAM param)
{
// default implementation
}
// Static factory method
public static CGfxMoveBase CreateMoveMethod(GfxMoveMode mode)
{
switch (mode)
{
case GfxMoveMode.enumLinearMove: return new CGfxLinearMove(mode);
default: return new CGfxLinearMove(mode);
}
}
}
```
## Inheritance Patterns
### C++ Pattern
```cpp
class CGfxLinearMove : public CGfxMoveBase
{
protected:
float m_fSpeed;
public:
CGfxLinearMove(GfxMoveMode mode) : CGfxMoveBase(mode) {}
virtual void StartMove(const A3DVECTOR3& vHost, const A3DVECTOR3& vTarget);
virtual bool TickMove(DWORD dwDeltaTime, ...);
};
```
### C# Pattern
```csharp
public class CGfxLinearMove : CGfxMoveBase
{
protected float m_fSpeed;
public CGfxLinearMove(GfxMoveMode mode) : base(mode) { }
public override void StartMove(Vector3 vHost, Vector3 vTarget)
{
// implementation
}
public override bool TickMove(uint dwDeltaTime, ...)
{
// implementation
}
}
```
## Static Factory Methods
### C++ Pattern
```cpp
inline CGfxMoveBase* CGfxMoveBase::CreateMoveMethod(GfxMoveMode mode)
{
switch(mode)
{
case enumLinearMove:
return new CGfxLinearMove(mode);
case enumOnTarget:
return new CGfxOnTargetMove(mode);
default:
assert(false);
return NULL;
}
}
```
### C# Pattern
```csharp
public static CGfxMoveBase CreateMoveMethod(GfxMoveMode mode)
{
switch (mode)
{
case GfxMoveMode.enumLinearMove:
return new CGfxLinearMove(mode);
case GfxMoveMode.enumOnTarget:
return new CGfxOnTargetMove(mode);
default:
return new CGfxLinearMove(mode); // fallback
}
}
```
## Vector Operations
### Normalize Pattern
**C++:**
```cpp
A3DVECTOR3 vDir = vTarget - m_vPos;
float fDist = vDir.Normalize(); // In-place normalize, returns magnitude
if (fDist < 1e-4f) return true;
```
**C#:**
```csharp
Vector3 vDir = vTarget - m_vPos;
float fDist = Normalize(ref vDir); // Helper method
if (fDist < 1e-4f) return true;
// Helper implementation:
protected static float Normalize(ref Vector3 v)
{
float mag = v.magnitude;
if (mag < 1e-6f) { v = Vector3.zero; return 0f; }
v /= mag;
return mag;
}
```
### Vector Math
**C++:**
```cpp
m_vPos += vFlyDir * fFlyDist;
m_vMoveDir = vFlyDir;
```
**C#:**
```csharp
m_vPos += vFlyDir * fFlyDist;
m_vMoveDir = vFlyDir;
```
## Protected Helper Methods
### C++ Pattern
```cpp
protected:
void CalcRange(const A3DVECTOR3& vDir)
{
m_vYRange = _unit_y;
m_vZRange.Set(vDir.x, 0, vDir.z);
if (m_vZRange.Normalize() < .01f) m_vZRange = _unit_z;
m_vXRange = CrossProduct(m_vYRange, m_vZRange);
// ...
}
A3DVECTOR3 GetRandOff() const
{
if (m_Shape == enumBox)
{
// ...
}
// ...
}
```
### C# Pattern
```csharp
protected void CalcRange(Vector3 vDir)
{
m_vYRange = Vector3.up;
m_vZRange = new Vector3(vDir.x, 0, vDir.z);
if (Normalize(ref m_vZRange) < 0.01f) m_vZRange = Vector3.forward;
m_vXRange = Vector3.Cross(m_vYRange, m_vZRange);
// ...
}
protected Vector3 GetRandOff()
{
if (m_Shape == EmitShape.enumBox)
{
// ...
}
// ...
}
```
## State Machine Pattern
### C++ Pattern
```cpp
enum
{
enumWait,
enumFlying,
enumHit,
enumFinished
} m_enumState;
void Tick(DWORD dwDeltaTime)
{
if (m_enumState == enumFinished) return;
else if (m_enumState == enumHit)
{
// handle hit state
}
else if (m_enumState == enumWait)
{
if (m_dwCurSpan < m_dwDelayTime) return;
m_enumState = enumFlying;
}
else // enumFlying
{
if (m_pMoveMethod.TickMove(dwDeltaTime, ...))
HitTarget(GetTargetCenter());
}
}
```
### C# Pattern
```csharp
protected GfxSkillEventState m_enumState;
public virtual void Tick(uint dwDeltaTime)
{
if (m_enumState == GfxSkillEventState.enumFinished) return;
else if (m_enumState == GfxSkillEventState.enumHit)
{
// handle hit state
}
else if (m_enumState == GfxSkillEventState.enumWait)
{
if (m_dwCurSpan < m_dwDelayTime) return;
m_enumState = GfxSkillEventState.enumFlying;
}
else // enumFlying
{
if (m_pMoveMethod.TickMove(dwDeltaTime, ...))
HitTarget(GetTargetCenter());
}
}
```
## Const Correctness → Readonly
### C++ Pattern
```cpp
const A3DVECTOR3& GetPos() const { return m_vPos; }
GfxMoveMode GetMode() const { return m_Mode; }
```
### C# Pattern
```csharp
public Vector3 GetPos() { return m_vPos; } // No const needed
public GfxMoveMode GetMode() { return m_Mode; } // No const needed
```
## Delegate Pattern (Virtual Methods)
### C++ Pattern
```cpp
class A3DSkillGfxEvent
{
CGfxMoveBase* m_pMoveMethod;
public:
GfxMoveMode GetMode() const { return m_pMoveMethod->GetMode(); }
void SetReverse(bool bReverse) const { m_pMoveMethod->SetReverse(bReverse); }
void SetParam(const GFX_SKILL_PARAM* param) { m_pMoveMethod->SetParam(param); }
};
```
### C# Pattern
```csharp
public class A3DSkillGfxEvent
{
protected CGfxMoveBase m_pMoveMethod;
public GfxMoveMode GetMode() { return m_pMoveMethod.GetMode(); }
public void SetReverse(bool bReverse) { m_pMoveMethod.SetReverse(bReverse); }
public void SetParam(GFX_SKILL_PARAM param) { m_pMoveMethod.SetParam(param); }
}
```
## Random Number Generation
### C++ Pattern
```cpp
float _SymmetricRandom() { return (rand() / (float)RAND_MAX) * 2.0f - 1.0f; }
float _UnitRandom() { return rand() / (float)RAND_MAX; }
A3DVECTOR3 GetRandOff() const
{
if (m_Shape == enumBox)
{
A3DVECTOR3 xOff, yOff, zOff;
xOff = _SymmetricRandom() * m_vXRange;
yOff = _SymmetricRandom() * m_vYRange;
zOff = _SymmetricRandom() * m_vZRange;
return xOff + yOff + zOff;
}
}
```
### C# Pattern
```csharp
private static float SymRandom()
{
return UnityEngine.Random.value * 2f - 1f;
}
private static float UnitRandom()
{
return UnityEngine.Random.value;
}
protected Vector3 GetRandOff()
{
if (m_Shape == EmitShape.enumBox)
{
Vector3 xOff = SymRandom() * m_vXRange;
Vector3 yOff = SymRandom() * m_vYRange;
Vector3 zOff = SymRandom() * m_vZRange;
return xOff + yOff + zOff;
}
}
```
## Conditional Compilation → #if UNITY_EDITOR
### C++ Pattern
```cpp
#ifdef _DEBUG
assert(false);
#endif
```
### C# Pattern
```csharp
#if UNITY_EDITOR
UnityEngine.Debug.Assert(false);
#endif
```
## Memory Management Patterns
### C++ Pattern
```cpp
void ReleaseFlyGfx()
{
if (m_pFlyGfx)
{
if (m_bFadeOut)
AfxGetGFXExMan()->QueueFadeOutGfx(m_pFlyGfx, 1000);
else
{
m_pFlyGfx->Release();
delete m_pFlyGfx;
}
m_pFlyGfx = NULL;
}
}
```
### C# Pattern
```csharp
protected void ReleaseFlyGfx()
{
if (m_pFlyGfx != null)
{
if (m_bFadeOut)
AfxGetGFXExMan().QueueFadeOutGfx(m_pFlyGfx, 1000);
else
{
m_pFlyGfx.Release();
// C#: Automatic garbage collection, no delete needed
}
m_pFlyGfx = null;
}
}
```
## Common Conversion Checklist
When converting a class:
- [ ] Abstract base → `abstract class`
- [ ] Pure virtual methods → `abstract` methods
- [ ] Virtual with default → `virtual` methods
- [ ] Non-virtual → regular methods
- [ ] Static factory → `static` method
- [ ] Const methods → regular methods (no const)
- [ ] Pointers → references (remove `*`)
- [ ] References → value types or `ref`/`out`
- [ ] `DWORD``uint`
- [ ] `A3DVECTOR3``Vector3`
- [ ] Union access → `param.value.fVal`
- [ ] Hungarian notation → preserved