482 lines
16 KiB
C#
482 lines
16 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Runtime.InteropServices;
|
|
using BrewMonster.Scripts;
|
|
using CSNetwork.GPDataType;
|
|
using UnityEngine;
|
|
|
|
using CombinedActMap = System.Collections.Generic.Dictionary<string, object>;
|
|
using CoGfxMap = System.Collections.Generic.Dictionary<string, object>;
|
|
using ConvexHullDataArray = System.Collections.Generic.List<object>;
|
|
using ECModelHookMap = System.Collections.Generic.Dictionary<string, object>;
|
|
using BrewMonster;
|
|
|
|
public enum ECMScript
|
|
{
|
|
enumECMScriptStartAction = 0,
|
|
enumECMScriptEndActioin,
|
|
enumECMScriptInit,
|
|
enumECMScriptRelease,
|
|
enumECMScriptModelLoaded,
|
|
enumECMScriptChangeEquip,
|
|
enumECMScriptChangeEquipTableInit,
|
|
enumECMScriptPhysBreak,
|
|
enumECMScriptCount
|
|
}
|
|
|
|
public enum ECMScriptVar
|
|
{
|
|
enumECMVarModel = 0,
|
|
enumECMVarActName,
|
|
enumECMVarActChannel,
|
|
enumECMVarEquipId,
|
|
enumECMVarEquipFlag,
|
|
enumECMVarFashionMode,
|
|
enumECMVarPathId,
|
|
enumECMVarId,
|
|
enumECMVarEquipIndex,
|
|
enumECMVarBreakOffsetX,
|
|
enumECMVarBreakOffsetY,
|
|
enumECMVarBreakOffsetZ,
|
|
enumECMVarCasterId,
|
|
enumECMVarCastTargetId,
|
|
enumECMVarSelf,
|
|
enumECMVarCount
|
|
}
|
|
|
|
public static class CECModelConstants
|
|
{
|
|
public const int ECM_SCRIPT_MAX_VAR_COUNT = 8;
|
|
public const int OUTER_DATA_COUNT = 8;
|
|
}
|
|
|
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
|
public struct ECM_SCRIPT_VAR
|
|
{
|
|
[MarshalAs(UnmanagedType.I4)]
|
|
public int var_count;
|
|
|
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = CECModelConstants.ECM_SCRIPT_MAX_VAR_COUNT)]
|
|
public int[] var_index;
|
|
}
|
|
|
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
|
public struct BoneScale
|
|
{
|
|
public int m_nIndex;
|
|
public int m_nType;
|
|
public A3DVECTOR3 m_vScale;
|
|
}
|
|
|
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
|
public struct BoneScaleEx
|
|
{
|
|
public int m_nIndex;
|
|
public float m_fLenFactor;
|
|
public float m_fThickFactor;
|
|
public float m_fWholeFactor;
|
|
}
|
|
|
|
public class ActChannelInfo
|
|
{
|
|
public List<string> bone_names = new List<string>();
|
|
public List<int> joint_indices = new List<int>();
|
|
|
|
public ActChannelInfo Clone()
|
|
{
|
|
return new ActChannelInfo
|
|
{
|
|
bone_names = new List<string>(bone_names),
|
|
joint_indices = new List<int>(joint_indices)
|
|
};
|
|
}
|
|
}
|
|
|
|
public enum A3DBLEND
|
|
{
|
|
A3DBLEND_SRCALPHA,
|
|
A3DBLEND_INVSRCALPHA
|
|
}
|
|
|
|
public struct A3DSHADER
|
|
{
|
|
public A3DBLEND SrcBlend;
|
|
public A3DBLEND DestBlend;
|
|
}
|
|
|
|
public class CECModelStaticData
|
|
{
|
|
private string m_strFilePath = string.Empty;
|
|
private string m_strSkinModelPath = string.Empty;
|
|
private bool m_bAutoUpdate = true;
|
|
private bool m_bActMapped;
|
|
private readonly CombinedActMap m_ActionMap = new CombinedActMap();
|
|
private uint m_dwVersion;
|
|
private string m_strHook = string.Empty;
|
|
private string m_strCCName = string.Empty;
|
|
private readonly List<BoneScale> m_BoneScales = new List<BoneScale>();
|
|
private readonly List<BoneScaleEx> m_BoneScaleExArr = new List<BoneScaleEx>();
|
|
private string m_strScaleBaseBone = string.Empty;
|
|
private uint m_OrgColor = 0xFFFFFFFF;
|
|
private uint m_EmissiveColor = 0;
|
|
private float m_fDefPlaySpeed = 1.0f;
|
|
private A3DSHADER m_BlendMode = new A3DSHADER
|
|
{
|
|
SrcBlend = A3DBLEND.A3DBLEND_SRCALPHA,
|
|
DestBlend = A3DBLEND.A3DBLEND_INVSRCALPHA
|
|
};
|
|
private readonly float[] m_OuterData = new float[CECModelConstants.OUTER_DATA_COUNT];
|
|
private bool m_bCanCastShadow = true;
|
|
private bool m_bRenderSkinModel = true;
|
|
private bool m_bRenderEdge = true;
|
|
private readonly CoGfxMap m_CoGfxMap = new CoGfxMap();
|
|
private readonly ConvexHullDataArray m_ConvexHullDataArr = new ConvexHullDataArray();
|
|
private readonly A3DAABB m_CHAABB = new A3DAABB();
|
|
private readonly Dictionary<int, ActChannelInfo> m_ChannelInfoDict = new Dictionary<int, ActChannelInfo>();
|
|
private readonly Dictionary<int, uint> m_EventMasks = new Dictionary<int, uint>();
|
|
private readonly string[] m_Scripts = new string[(int)ECMScript.enumECMScriptCount];
|
|
private readonly bool[] m_ScriptEnable = new bool[(int)ECMScript.enumECMScriptCount];
|
|
private readonly CLuaMemTbl m_ScriptMemTbl = new CLuaMemTbl();
|
|
private bool m_bInitGlobalScript;
|
|
private string m_strGlobalScriptName = string.Empty;
|
|
|
|
public class ChildInfo
|
|
{
|
|
public string m_strName = string.Empty;
|
|
public string m_strPath = string.Empty;
|
|
public string m_strHHName = string.Empty;
|
|
public string m_strCCName = string.Empty;
|
|
}
|
|
|
|
private readonly List<ChildInfo> m_ChildInfoArray = new List<ChildInfo>();
|
|
private readonly List<string> m_AdditionalSkinLst = new List<string>();
|
|
private string m_strPhysFileName = string.Empty;
|
|
private object m_pPhysSyncData;
|
|
private readonly ECModelHookMap m_ECModelHookMap = new ECModelHookMap();
|
|
private string m_strPixelShader = string.Empty;
|
|
private string m_strShaderTex = string.Empty;
|
|
private readonly List<object> m_vecPSConsts = new List<object>();
|
|
|
|
public CECModelStaticData()
|
|
{
|
|
ResetOuterData();
|
|
m_CHAABB.Clear();
|
|
}
|
|
|
|
public bool LoadData(string szModelFile, bool bLoadAdditionalSkin)
|
|
{
|
|
throw new NotImplementedException("CECModelStaticData.LoadData requires the legacy AFile system to be ported.");
|
|
}
|
|
|
|
public bool Save(string szFile, CECModel pModel)
|
|
{
|
|
throw new NotImplementedException("CECModelStaticData.Save requires the legacy serialization pipeline to be ported.");
|
|
}
|
|
|
|
public bool SaveBoneScaleInfo(string szFile)
|
|
{
|
|
throw new NotImplementedException("CECModelStaticData.SaveBoneScaleInfo is not yet implemented.");
|
|
}
|
|
|
|
public void Release()
|
|
{
|
|
m_BoneScales.Clear();
|
|
m_BoneScaleExArr.Clear();
|
|
m_CoGfxMap.Clear();
|
|
m_ActionMap.Clear();
|
|
m_AdditionalSkinLst.Clear();
|
|
m_ChildInfoArray.Clear();
|
|
m_ConvexHullDataArr.Clear();
|
|
m_ChannelInfoDict.Clear();
|
|
m_EventMasks.Clear();
|
|
Array.Clear(m_Scripts, 0, m_Scripts.Length);
|
|
Array.Clear(m_ScriptEnable, 0, m_ScriptEnable.Length);
|
|
m_ECModelHookMap.Clear();
|
|
m_vecPSConsts.Clear();
|
|
m_bInitGlobalScript = false;
|
|
m_strGlobalScriptName = string.Empty;
|
|
m_pPhysSyncData = null;
|
|
m_CHAABB.Clear();
|
|
ResetOuterData();
|
|
}
|
|
|
|
public ConvexHullDataArray GetConvexHullData() => m_ConvexHullDataArr;
|
|
|
|
public bool HasCHAABB() => m_ConvexHullDataArr.Count != 0;
|
|
|
|
public A3DAABB GetCHAABB() => m_CHAABB;
|
|
|
|
public bool UpdateScript(int index, string strScript, bool bCompileOnly)
|
|
{
|
|
if (index < 0 || index >= (int)ECMScript.enumECMScriptCount)
|
|
return false;
|
|
|
|
if (!bCompileOnly)
|
|
m_Scripts[index] = strScript ?? string.Empty;
|
|
|
|
m_ScriptEnable[index] = !string.IsNullOrEmpty(m_Scripts[index]);
|
|
return m_ScriptEnable[index];
|
|
}
|
|
|
|
public CoGfxMap GetCoGfxMap() => m_CoGfxMap;
|
|
|
|
public CombinedActMap GetCombinedActMap() => m_ActionMap;
|
|
|
|
public string GetPhysFileName() => m_strPhysFileName;
|
|
|
|
public void SetPhysFileName(string szFile) => m_strPhysFileName = szFile ?? string.Empty;
|
|
|
|
public object GetPhysSyncData() => m_pPhysSyncData;
|
|
|
|
public void SetPhysSyncData(object p) => m_pPhysSyncData = p;
|
|
|
|
public uint GetVersion() => m_dwVersion;
|
|
|
|
public string GetPixelShaderPath() => m_strPixelShader;
|
|
|
|
public void SetPixelShaderPath(string szPath) => m_strPixelShader = szPath ?? string.Empty;
|
|
|
|
public string GetShaderTexture() => m_strShaderTex;
|
|
|
|
public void SetShaderTexture(string szPath) => m_strShaderTex = szPath ?? string.Empty;
|
|
|
|
public IList<object> GetPSConstVec() => m_vecPSConsts;
|
|
|
|
public void SetActionEventMask(int nChannel, uint dwMask) => m_EventMasks[nChannel] = dwMask;
|
|
|
|
public uint GetActionEventMask(int nChannel)
|
|
{
|
|
return m_EventMasks.TryGetValue(nChannel, out uint mask) ? mask : uint.MaxValue;
|
|
}
|
|
|
|
public IReadOnlyDictionary<int, uint> GetActionEventMaskSnapshot() => m_EventMasks;
|
|
|
|
public void OnScriptEndAction(CECModel pModel, int nChannel, string szActName)
|
|
{
|
|
if (!IsScriptEnabled(ECMScript.enumECMScriptEndActioin))
|
|
return;
|
|
|
|
Debug.LogWarning($"CECModelStaticData.OnScriptEndAction invoked for {szActName}, scripting runtime not yet ported.");
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
m_OrgColor = 0xFFFFFFFF;
|
|
m_EmissiveColor = 0;
|
|
m_fDefPlaySpeed = 1.0f;
|
|
m_BlendMode = new A3DSHADER
|
|
{
|
|
SrcBlend = A3DBLEND.A3DBLEND_SRCALPHA,
|
|
DestBlend = A3DBLEND.A3DBLEND_INVSRCALPHA
|
|
};
|
|
|
|
ResetOuterData();
|
|
m_BoneScales.Clear();
|
|
m_BoneScaleExArr.Clear();
|
|
m_strScaleBaseBone = string.Empty;
|
|
m_ChannelInfoDict.Clear();
|
|
m_strPhysFileName = string.Empty;
|
|
}
|
|
|
|
public void AddScriptMethod(int index, string szScript)
|
|
{
|
|
if (index < 0 || index >= (int)ECMScript.enumECMScriptCount)
|
|
return;
|
|
|
|
m_ScriptEnable[index] = !string.IsNullOrEmpty(szScript);
|
|
}
|
|
|
|
public void OnScriptPlayAction(CECModel pModel, int nChannel, string szActName)
|
|
{
|
|
if (!IsScriptEnabled(ECMScript.enumECMScriptStartAction))
|
|
return;
|
|
|
|
Debug.LogWarning($"CECModelStaticData.OnScriptPlayAction triggered for {szActName}, scripting runtime not available.");
|
|
}
|
|
|
|
public void OnScriptChangeEquip(CECModel pModel, int nEquipId, int nEquipFlag, bool bFashionMode, int nPathId, int nEquipIndex)
|
|
{
|
|
if (!IsScriptEnabled(ECMScript.enumECMScriptChangeEquip))
|
|
return;
|
|
|
|
Debug.LogWarning("CECModelStaticData.OnScriptChangeEquip called, scripting runtime not available.");
|
|
}
|
|
|
|
public void OnScriptPhysBreak(CECModel pModel, float fBreakOffsetX, float fBreakOffsetY, float fBreakOffsetZ)
|
|
{
|
|
if (!IsScriptEnabled(ECMScript.enumECMScriptPhysBreak))
|
|
return;
|
|
|
|
Debug.LogWarning("CECModelStaticData.OnScriptPhysBreak called, scripting runtime not available.");
|
|
}
|
|
|
|
public void InitGlobalScript()
|
|
{
|
|
if (m_bInitGlobalScript)
|
|
return;
|
|
|
|
if (!IsScriptEnabled(ECMScript.enumECMScriptInit))
|
|
return;
|
|
|
|
m_bInitGlobalScript = true;
|
|
m_strGlobalScriptName = $"GlobalScriptFunc_{DateTime.UtcNow.Ticks}";
|
|
}
|
|
|
|
public bool LoadAdditionalSkin(object pFile, uint dwVersion, bool bLoadAdditionalSkin)
|
|
{
|
|
Debug.LogWarning("CECModelStaticData.LoadAdditionalSkin stub invoked.");
|
|
return true;
|
|
}
|
|
|
|
public IList<string> GetAdditionalSkinList() => m_AdditionalSkinLst;
|
|
|
|
public IList<ChildInfo> GetChildInfoArray() => m_ChildInfoArray;
|
|
|
|
public float[] GetOuterData() => m_OuterData;
|
|
|
|
public bool CanCastShadow => m_bCanCastShadow;
|
|
public bool CanRenderSkinModel => m_bRenderSkinModel;
|
|
public bool CanRenderEdge => m_bRenderEdge;
|
|
|
|
private bool IsScriptEnabled(ECMScript scriptId)
|
|
{
|
|
int idx = (int)scriptId;
|
|
if (idx < 0 || idx >= m_ScriptEnable.Length)
|
|
return false;
|
|
return m_ScriptEnable[idx];
|
|
}
|
|
|
|
private void ResetOuterData()
|
|
{
|
|
for (int i = 0; i < m_OuterData.Length; i++)
|
|
m_OuterData[i] = 1.0f;
|
|
}
|
|
}
|
|
|
|
public class CLuaMemTbl
|
|
{
|
|
public void Init(string tableName) { }
|
|
public bool AddMethod(string name, IList<string> args, string script) => false;
|
|
public void RemoveMethod(string name) { }
|
|
public void Release() { }
|
|
}
|
|
|
|
public class CECModel
|
|
{
|
|
private const uint COMACT_FLAG_MODE_NONE = 0;
|
|
protected CECModelStaticData m_pMapModel;
|
|
public void ClearComActFlag(bool bSignalCurrent) { ClearComActFlag(0, bSignalCurrent); }
|
|
public void ClearComActFlag(int nChannel, bool bSignalCurrent)
|
|
{
|
|
/* ChannelAct & ca = m_ChannelActs[nChannel];
|
|
ChannelActNode* pNode = ca.GetHighestRankNode();
|
|
|
|
if (pNode)
|
|
{
|
|
if (pNode->m_pActFlag && bSignalCurrent)
|
|
*pNode->m_pActFlag = true;
|
|
|
|
//ca.m_dwFlagMode = COMACT_FLAG_MODE_NONE;
|
|
pNode->m_pActFlag = NULL;
|
|
}*/
|
|
}
|
|
public bool QueueAction(CECNPC.INFO iNFO, string szActName, ref bool pNewActFlag, int nTransTime = 200, uint dwUserData = 0, bool bForceStopPrevAct = false, bool bCheckTailDup = false, bool bNoFx = false, bool bResetSpeed = false
|
|
/*joslian*/, bool bResetActFlag = false, uint dwNewFlagMode = COMACT_FLAG_MODE_NONE)
|
|
{
|
|
QueueAction(iNFO, 0, szActName, ref bResetActFlag, nTransTime, dwUserData, bForceStopPrevAct, bCheckTailDup, bNoFx, bResetSpeed/*joslian*/, pNewActFlag, dwNewFlagMode);
|
|
return true;
|
|
}
|
|
public bool QueueAction(CECNPC.INFO iNFO, int nChannel, string szActName, ref bool pNewActFlag, int nTransTime, uint dwUserData/* 0 */, bool bForceStopPrevAct, bool bCheckTailDup, bool bNoFx, bool bResetSpeed
|
|
/*joslian*/, bool bResetActFlag, uint dwNewFlagMode)
|
|
{
|
|
|
|
EventBus.PublishChannel(iNFO.nid, new QueueNPCActionEvent(szActName));
|
|
return true;
|
|
}
|
|
public void StopChannelAction(int nChannel, bool bStopAct, bool bStopFx = false)
|
|
{
|
|
//TODO: Implement StopChannelAction
|
|
}
|
|
public struct QueueNPCActionEvent
|
|
{
|
|
public string AnimationName;
|
|
public QueueNPCActionEvent(string animationName)
|
|
{
|
|
AnimationName = animationName;
|
|
}
|
|
}
|
|
public bool HasCHAABB() { return m_pMapModel.HasCHAABB(); }
|
|
|
|
public void PlayGfx(string szPath, string szHook, float fScale, bool bFadeOut, A3DVECTOR3 vOffset, float fPitch, float fYaw, float fRot, bool bUseECMHook, uint dwFadeOutTime)
|
|
{
|
|
if (!bFadeOut)
|
|
dwFadeOutTime = 0;
|
|
string strKey = szPath;
|
|
strKey += szHook;
|
|
|
|
|
|
// PGFX_INFO pInfo;
|
|
//
|
|
// CoGfxMap::iterator it = m_CoGfxMap.find(strKey);
|
|
// if (bUseECMHook) {
|
|
// if (CECModelHook* pHook = GetECMHook(szHook))
|
|
// {
|
|
// fScale *= pHook->GetScaleFactor();
|
|
// }
|
|
// }
|
|
//
|
|
// if (it != m_CoGfxMap.end())
|
|
// {
|
|
// pInfo = it->second;
|
|
// A3DGFXEx* pGfx = pInfo->GetGfx();
|
|
// TransferEcmProperties(pGfx);
|
|
// pGfx->SetScale(fScale * m_fGfxScaleFactor);
|
|
// pInfo->SetFadeOutTime(dwFadeOutTime);
|
|
// pInfo->SetModelAlpha(true);
|
|
// pInfo->SetHookName(szHook);
|
|
// pInfo->SetUseECMHook(bUseECMHook);
|
|
// pInfo->SetScale(fScale);
|
|
// pInfo->SetOffset(vOffset);
|
|
// pInfo->SetPitch(fPitch);
|
|
// pInfo->SetYaw(fYaw);
|
|
// pInfo->SetRot(fRot);
|
|
// pInfo->BuildTranMat();
|
|
// pGfx->SetSfxPriority(m_nSfxPriority);
|
|
// pGfx->Start(true);
|
|
// return;
|
|
// }
|
|
//
|
|
// pInfo = new GFX_INFO(NULL);
|
|
// pInfo->SetFilePath(szPath);
|
|
// pInfo->SetHookName(szHook);
|
|
// pInfo->SetUseECMHook(bUseECMHook);
|
|
// pInfo->SetScale(fScale);
|
|
// pInfo->Init(m_pA3DDevice);
|
|
// pInfo->SetOffset(vOffset);
|
|
// pInfo->SetPitch(fPitch);
|
|
// pInfo->SetYaw(fYaw);
|
|
// pInfo->SetRot(fRot);
|
|
// pInfo->LoadGfx();
|
|
//
|
|
// if (!pInfo->GetGfx())
|
|
// {
|
|
// delete pInfo;
|
|
// return;
|
|
// }
|
|
//
|
|
// pInfo->BuildTranMat();
|
|
// pInfo->SetFadeOutTime(dwFadeOutTime);
|
|
// pInfo->SetModelAlpha(true);
|
|
// TransferEcmProperties(pInfo->GetGfx());
|
|
// pInfo->GetGfx()->SetScale(fScale * m_fGfxScaleFactor);
|
|
// pInfo->GetGfx()->SetSfxPriority(m_nSfxPriority);
|
|
// pInfo->GetGfx()->Start(true);
|
|
//
|
|
// m_CoGfxMap[strKey] = pInfo;
|
|
}
|
|
}
|
|
// Action channel
|
|
public enum ActionChannel
|
|
{
|
|
ACTCHA_WOUND = 1,
|
|
}; |