From c6f24993b5fc6deca6416587d9c1d0fa231ea436 Mon Sep 17 00:00:00 2001 From: NguyenVanDat Date: Thu, 13 Nov 2025 17:12:41 +0700 Subject: [PATCH] show selecting vfx and elase player enter vfx --- .../Environment/角色出现人类 Variant.prefab | 88 ++++++ .../角色出现人类 Variant.prefab.meta | 7 + .../PerfectWorld/Scripts/MainFiles/EC_Game.cs | 246 ++++++++++------- .../Scripts/Managers/EC_ManPlayer.cs | 4 +- .../Scripts/Players/EC_ElsePlayer.cs | 23 +- Assets/Scripts/CECHostPlayer.cs | 255 +++++++++--------- Assets/Scripts/Utilities/EC_Resource.cs | 27 +- 7 files changed, 418 insertions(+), 232 deletions(-) create mode 100644 Assets/Jianghu/Prefabs/Environment/角色出现人类 Variant.prefab create mode 100644 Assets/Jianghu/Prefabs/Environment/角色出现人类 Variant.prefab.meta diff --git a/Assets/Jianghu/Prefabs/Environment/角色出现人类 Variant.prefab b/Assets/Jianghu/Prefabs/Environment/角色出现人类 Variant.prefab new file mode 100644 index 0000000000..f95ca6b13c --- /dev/null +++ b/Assets/Jianghu/Prefabs/Environment/角色出现人类 Variant.prefab @@ -0,0 +1,88 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1001 &236266617410040009 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + serializedVersion: 3 + m_TransformParent: {fileID: 0} + m_Modifications: + - target: {fileID: 919479894471096875, guid: 18a78c9a6d2a42a439ac7f99d632bde7, type: 3} + propertyPath: m_LocalPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 919479894471096875, guid: 18a78c9a6d2a42a439ac7f99d632bde7, type: 3} + propertyPath: m_LocalPosition.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 919479894471096875, guid: 18a78c9a6d2a42a439ac7f99d632bde7, type: 3} + propertyPath: m_LocalPosition.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 919479894471096875, guid: 18a78c9a6d2a42a439ac7f99d632bde7, type: 3} + propertyPath: m_LocalRotation.w + value: 0.7071068 + objectReference: {fileID: 0} + - target: {fileID: 919479894471096875, guid: 18a78c9a6d2a42a439ac7f99d632bde7, type: 3} + propertyPath: m_LocalRotation.x + value: -0.7071068 + objectReference: {fileID: 0} + - target: {fileID: 919479894471096875, guid: 18a78c9a6d2a42a439ac7f99d632bde7, type: 3} + propertyPath: m_LocalRotation.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 919479894471096875, guid: 18a78c9a6d2a42a439ac7f99d632bde7, type: 3} + propertyPath: m_LocalRotation.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 919479894471096875, guid: 18a78c9a6d2a42a439ac7f99d632bde7, type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: -90 + objectReference: {fileID: 0} + - target: {fileID: 919479894471096875, guid: 18a78c9a6d2a42a439ac7f99d632bde7, type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 919479894471096875, guid: 18a78c9a6d2a42a439ac7f99d632bde7, type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 5001274398267972232, guid: 18a78c9a6d2a42a439ac7f99d632bde7, type: 3} + propertyPath: m_Name + value: "\u89D2\u8272\u51FA\u73B0\u4EBA\u7C7B Variant" + objectReference: {fileID: 0} + m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: + - targetCorrespondingSourceObject: {fileID: 5001274398267972232, guid: 18a78c9a6d2a42a439ac7f99d632bde7, type: 3} + insertIndex: -1 + addedObject: {fileID: 3519155159441343304} + m_SourcePrefab: {fileID: 100100000, guid: 18a78c9a6d2a42a439ac7f99d632bde7, type: 3} +--- !u!198 &3386267201826864132 stripped +ParticleSystem: + m_CorrespondingSourceObject: {fileID: 3294685667945090253, guid: 18a78c9a6d2a42a439ac7f99d632bde7, type: 3} + m_PrefabInstance: {fileID: 236266617410040009} + m_PrefabAsset: {fileID: 0} +--- !u!1 &5057396892305369665 stripped +GameObject: + m_CorrespondingSourceObject: {fileID: 5001274398267972232, guid: 18a78c9a6d2a42a439ac7f99d632bde7, type: 3} + m_PrefabInstance: {fileID: 236266617410040009} + m_PrefabAsset: {fileID: 0} +--- !u!114 &3519155159441343304 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5057396892305369665} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 9dcde7b030da4a94a9b5c05323a411bf, type: 3} + m_Name: + m_EditorClassIdentifier: + _vfx: {fileID: 3386267201826864132} + _lifeTime: -1 + _isLoopVfx: 0 + m_iState: 0 diff --git a/Assets/Jianghu/Prefabs/Environment/角色出现人类 Variant.prefab.meta b/Assets/Jianghu/Prefabs/Environment/角色出现人类 Variant.prefab.meta new file mode 100644 index 0000000000..5be5bcced1 --- /dev/null +++ b/Assets/Jianghu/Prefabs/Environment/角色出现人类 Variant.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 1cfde61ea9d19614a8ea91cb1eeca97b +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/PerfectWorld/Scripts/MainFiles/EC_Game.cs b/Assets/PerfectWorld/Scripts/MainFiles/EC_Game.cs index dd183c56a3..32ed834533 100644 --- a/Assets/PerfectWorld/Scripts/MainFiles/EC_Game.cs +++ b/Assets/PerfectWorld/Scripts/MainFiles/EC_Game.cs @@ -11,44 +11,79 @@ namespace BrewMonster.Network public partial class EC_Game { #region Fields - private static ATaskTemplMan m_pTaskMan; // Task template manager - private static elementdataman m_pElementDataMan; // global element templates manager - private static CECGameRun m_pGameRun; // Game running object - private static CECGFXCaster m_pGFXCaster; // GFX caster - private static BrewMonster.CECStringTab m_FixedMsgs; // Fixed message table - private static BrewMonster.CECStringTab m_ItemDesc; // Item desciption string table - private static BrewMonster.CECStringTab m_ItemExtDesc; // Item extend description string table - private static BrewMonster.CECStringTab m_SkillDesc; // Skill description string table - private static BrewMonster.CECStringTab m_BuffDesc; // Buff description string table - private static Dictionary m_ItemMsgMap; // TemplateId -> (MessageId, DisplayMode) + private static ATaskTemplMan m_pTaskMan; // Task template manager + private static elementdataman m_pElementDataMan; // global element templates manager + private static CECGameRun m_pGameRun; // Game running object + private static CECGFXCaster m_pGFXCaster; // GFX caster + + private static BrewMonster.CECStringTab m_FixedMsgs; // Fixed message table + private static BrewMonster.CECStringTab m_ItemDesc; // Item desciption string table + private static BrewMonster.CECStringTab m_ItemExtDesc; // Item extend description string table + private static BrewMonster.CECStringTab m_SkillDesc; // Skill description string table + private static BrewMonster.CECStringTab m_BuffDesc; // Buff description string table + private static Dictionary m_ItemMsgMap; // TemplateId -> (MessageId, DisplayMode) + + private static int m_iCurCursor; // Current cursor + #endregion #region Properties - public static ATaskTemplMan GetTaskTemplateMan() { return m_pTaskMan; } - public static elementdataman GetElementDataMan() { return m_pElementDataMan; } - + + public static ATaskTemplMan GetTaskTemplateMan() + { + return m_pTaskMan; + } + + public static elementdataman GetElementDataMan() + { + return m_pElementDataMan; + } + // String table getters - public static BrewMonster.CECStringTab GetFixedMsgs() { return m_FixedMsgs; } - public static BrewMonster.CECStringTab GetItemDesc() { return m_ItemDesc; } - public static BrewMonster.CECStringTab GetItemExtDesc() { return m_ItemExtDesc; } - public static BrewMonster.CECStringTab GetSkillDesc() { return m_SkillDesc; } - public static BrewMonster.CECStringTab GetBuffDesc() { return m_BuffDesc; } - public static bool TryGetItemMsg(int templateId, out int messageId, out int displayMode) - { - messageId = 0; - displayMode = 0; - if (m_ItemMsgMap != null && m_ItemMsgMap.TryGetValue(templateId, out var entry)) - { - messageId = entry.MessageId; - displayMode = entry.DisplayMode; - return true; - } - return false; - } + public static BrewMonster.CECStringTab GetFixedMsgs() + { + return m_FixedMsgs; + } + + public static BrewMonster.CECStringTab GetItemDesc() + { + return m_ItemDesc; + } + + public static BrewMonster.CECStringTab GetItemExtDesc() + { + return m_ItemExtDesc; + } + + public static BrewMonster.CECStringTab GetSkillDesc() + { + return m_SkillDesc; + } + + public static BrewMonster.CECStringTab GetBuffDesc() + { + return m_BuffDesc; + } + + public static bool TryGetItemMsg(int templateId, out int messageId, out int displayMode) + { + messageId = 0; + displayMode = 0; + if (m_ItemMsgMap != null && m_ItemMsgMap.TryGetValue(templateId, out var entry)) + { + messageId = entry.MessageId; + displayMode = entry.DisplayMode; + return true; + } + + return false; + } + #endregion #region Public Methods + public static bool Init() { m_pElementDataMan = elementdataman.Instance; @@ -59,9 +94,10 @@ namespace BrewMonster.Network m_pTaskMan.Init(m_pElementDataMan); if (!m_pTaskMan.InitStorageTask()) { - BMLogger.LogError("[Dat]- CECGame::Init, Storage task Init Failed!"); + BMLogger.LogError("[Dat]- CECGame::Init, Storage task Init Failed!"); return false; } + m_pGameRun = CECGameRun.Instance; if (m_pGameRun == null) { @@ -72,16 +108,16 @@ namespace BrewMonster.Network // Create GFX caster if (m_pGFXCaster == null) { - m_pGFXCaster = new CECGFXCaster(); - return false; + m_pGFXCaster = new CECGFXCaster(); + return false; } - + // Initialize string tables InitializeStringTables(); - + return true; } - + /// /// Initialize all string tables with their respective data files /// @@ -93,44 +129,44 @@ namespace BrewMonster.Network m_ItemExtDesc = new BrewMonster.CECStringTab(); m_SkillDesc = new BrewMonster.CECStringTab(); m_BuffDesc = new BrewMonster.CECStringTab(); - + // Load string files from StreamingAssets/configs directory string dataPath = Application.streamingAssetsPath + "/configs/"; - - try + + try { // Load each string table using the actual file names from StreamingAssets/configs if (!m_FixedMsgs.Init(dataPath + "fixed_msg.txt", true)) { Debug.LogWarning("[EC_Game] Failed to load fixed_msg.txt"); } - + if (!m_ItemDesc.Init(dataPath + "item_desc.txt", true)) { Debug.LogWarning("[EC_Game] Failed to load item_desc.txt"); } - + if (!m_ItemExtDesc.Init(dataPath + "item_ext_desc.txt", true)) { Debug.LogWarning("[EC_Game] Failed to load item_ext_desc.txt"); } - + if (!m_SkillDesc.Init(dataPath + "skillstr.txt", true)) { Debug.LogWarning("[EC_Game] Failed to load skillstr.txt"); } - + // Note: There's no buff_desc.txt file in the configs folder // You may need to create this file or use a different source for buff descriptions if (!m_BuffDesc.Init(dataPath + "buff_desc.txt", true)) { Debug.LogWarning("[EC_Game] Failed to load buff_desc.txt - file may not exist"); } - - // Load item message map (template -> message id) - LoadItemMsgMap(); - - Debug.Log("[EC_Game] String tables initialized successfully"); + + // Load item message map (template -> message id) + LoadItemMsgMap(); + + Debug.Log("[EC_Game] String tables initialized successfully"); } catch (System.Exception ex) { @@ -138,53 +174,83 @@ namespace BrewMonster.Network } } - private struct ItemMsgMapEntry - { - public int MessageId; - public int DisplayMode; - } + private struct ItemMsgMapEntry + { + public int MessageId; + public int DisplayMode; + } - private static void LoadItemMsgMap() - { - m_ItemMsgMap = new Dictionary(); - try - { - string path = Application.streamingAssetsPath + "/configs/item_msg_map.txt"; - if (!File.Exists(path)) - { - Debug.LogWarning("[EC_Game] item_msg_map.txt not found; descriptions will fall back to template IDs"); - return; - } + private static void LoadItemMsgMap() + { + m_ItemMsgMap = new Dictionary(); + try + { + string path = Application.streamingAssetsPath + "/configs/item_msg_map.txt"; + if (!File.Exists(path)) + { + Debug.LogWarning( + "[EC_Game] item_msg_map.txt not found; descriptions will fall back to template IDs"); + return; + } - foreach (var raw in File.ReadLines(path)) - { - var line = raw.Trim(); - if (line.Length == 0) continue; - if (line.StartsWith("//")) continue; + foreach (var raw in File.ReadLines(path)) + { + var line = raw.Trim(); + if (line.Length == 0) continue; + if (line.StartsWith("//")) continue; - // Expect: templateId messageId displayMode - var parts = line.Split(new char[] { '\t', ' ' }, System.StringSplitOptions.RemoveEmptyEntries); - if (parts.Length < 2) continue; - if (!int.TryParse(parts[0], out int templateId)) continue; - if (!int.TryParse(parts[1], out int messageId)) continue; - int displayMode = 0; - if (parts.Length >= 3) int.TryParse(parts[2], out displayMode); + // Expect: templateId messageId displayMode + var parts = line.Split(new char[] { '\t', ' ' }, System.StringSplitOptions.RemoveEmptyEntries); + if (parts.Length < 2) continue; + if (!int.TryParse(parts[0], out int templateId)) continue; + if (!int.TryParse(parts[1], out int messageId)) continue; + int displayMode = 0; + if (parts.Length >= 3) int.TryParse(parts[2], out displayMode); - m_ItemMsgMap[templateId] = new ItemMsgMapEntry { MessageId = messageId, DisplayMode = displayMode }; - } - } - catch (System.Exception ex) - { - Debug.LogWarning($"[EC_Game] Failed to load item_msg_map: {ex.Message}"); - } - } - public static CECGameRun GetGameRun() { return m_pGameRun; } + m_ItemMsgMap[templateId] = new ItemMsgMapEntry { MessageId = messageId, DisplayMode = displayMode }; + } + } + catch (System.Exception ex) + { + Debug.LogWarning($"[EC_Game] Failed to load item_msg_map: {ex.Message}"); + } + } + + public static CECGameRun GetGameRun() + { + return m_pGameRun; + } + + public static CECGFXCaster GetGFXCaster() + { + if (m_pGFXCaster == null) m_pGFXCaster = new CECGFXCaster(); + return m_pGFXCaster; + } + + // Change current cursor + public static int ChangeCursor(int iCursor) + { + if (iCursor == m_iCurCursor) + return iCursor; + + // if (m_aCursors[iCursor]) + // m_pA3DDevice->SetCursor(m_aCursors[iCursor]); + // + // // force show this cursor + // ShowCursor(g_pGame->GetA3DDevice()->GetShowCursor()); + // + // if( l_idMainThread != GetCurrentThreadId() ) + // { + // // ::SetCursor must be called from main thread to take effects, so here we should post a WM_SETCURSOR message + // // to ensure the main thread receive WM_SETCURSOR and update the cursor again + // PostMessage(m_GameInit.hWnd, WM_SETCURSOR, (WPARAM)m_GameInit.hWnd, MAKELPARAM(HTCLIENT, WM_MOUSEMOVE)); + // } + + int iOldCursor = m_iCurCursor; + m_iCurCursor = iCursor; + return iOldCursor; + } - public static CECGFXCaster GetGFXCaster() - { - if(m_pGFXCaster==null) m_pGFXCaster = new CECGFXCaster(); - return m_pGFXCaster; - } #endregion } } \ No newline at end of file diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_ManPlayer.cs b/Assets/PerfectWorld/Scripts/Managers/EC_ManPlayer.cs index 28a53e34c1..cb7df5e4b6 100644 --- a/Assets/PerfectWorld/Scripts/Managers/EC_ManPlayer.cs +++ b/Assets/PerfectWorld/Scripts/Managers/EC_ManPlayer.cs @@ -339,7 +339,7 @@ namespace PerfectWorld.Scripts.Managers if (pPlayer.gameObject != null) { // This player has existed in player table, call special initial function - pPlayer.Init(roleInfo, info); + pPlayer.Init(roleInfo, info, iAppearFlag); return pPlayer; } else @@ -376,7 +376,7 @@ namespace PerfectWorld.Scripts.Managers GameObject ob = CECGameRun.Instance.InitCharacter(info); EC_ElsePlayer elsePlayer = ob.AddComponent(); - elsePlayer.Init(roleInfo, info); + elsePlayer.Init(roleInfo, info, iAppearFlag); return elsePlayer; } diff --git a/Assets/PerfectWorld/Scripts/Players/EC_ElsePlayer.cs b/Assets/PerfectWorld/Scripts/Players/EC_ElsePlayer.cs index 356e3233c0..7f9dcf5baf 100644 --- a/Assets/PerfectWorld/Scripts/Players/EC_ElsePlayer.cs +++ b/Assets/PerfectWorld/Scripts/Players/EC_ElsePlayer.cs @@ -31,11 +31,13 @@ namespace PerfectWorld.Scripts.Player OtherPlayer_Move_Info m_cdr = new OtherPlayer_Move_Info(); float m_fDistToHost = 0f; // Distance to host player float m_fDistToHostH = 0f; // Horizontal distance to host player + private int m_iAppearFlag; + private BaseVfxObject m_pAppearGFX; // Appear GFX public CECCounter m_FightCnt; CECEPWorkMan m_pEPWorkMan; CECHostPlayer pHost => EC_ManMessageMono.Instance?.GetECManPlayer?.GetHostPlayer(); - public void Init(RoleInfo roleInfo, info_player_1 Info) + public void Init(RoleInfo roleInfo, info_player_1 Info, int iAppearFlag) { SetUpPlayer(); m_dwResFlags = (uint)PlayerResourcesReadyFlag.RESFG_ALL; @@ -68,10 +70,10 @@ namespace PerfectWorld.Scripts.Player if (TryGetComponent(out var visual)) { - - visual.InitPlayerEventDoneHandler(); } + + LoadAppearGfx(); } public void MoveTo(cmd_object_move Cmd) { @@ -438,7 +440,20 @@ namespace PerfectWorld.Scripts.Player // Enter fight state EnterFightState(); } - + + private async void LoadAppearGfx() + { + if (!m_pAppearGFX && m_iAppearFlag == (int)PlayerAppearFlag.APPEAR_ENTERWORLD) + { + CECGFXCaster pGfxCaster = EC_Game.GetGFXCaster(); + + m_pAppearGFX = await pGfxCaster.LoadGFXEx(EC_Resource.res_GFXFile((int)GfxResourceType.RES_GFX_PLAYERAPPEAR)); + var pos = GetPos(); + m_pAppearGFX.transform.position = new Vector3(pos.x, pos.y, pos.z); + m_pAppearGFX.transform.parent = transform; + m_pAppearGFX.Play(); + } + } // Play an attack effect //void PlayAttackEffect(int idTarget, int idSkill, int skillLevel, int nDamage, // uint dwModifier, int nAttackSpeed, int[] piAttackTime/* NULL */, int nSection) diff --git a/Assets/Scripts/CECHostPlayer.cs b/Assets/Scripts/CECHostPlayer.cs index c197aa36b1..1e1f423d05 100644 --- a/Assets/Scripts/CECHostPlayer.cs +++ b/Assets/Scripts/CECHostPlayer.cs @@ -114,6 +114,13 @@ public partial class CECHostPlayer : CECPlayer private BaseVfxObject m_pSelectedGFX; private BaseVfxObject m_pHoverGFX; + // Cursor estimation optimization + private Vector2 m_lastMousePosition; + private float m_cursorUpdateTimer; + private const float CURSOR_UPDATE_INTERVAL = 0.05f; // 20 times per second instead of 60+ + private UnityEngine.InputSystem.Mouse m_cachedMouse; + private UnityEngine.InputSystem.Keyboard m_cachedKeyboard; + public bool IsChangingFace() { return m_bChangingFace; } private void Awake() @@ -194,6 +201,10 @@ public partial class CECHostPlayer : CECPlayer _playerStateMachine.InitState(_idleState); // btnJump.onClick.AddListener(HandleJump); + + // Cache input devices for better performance + m_cachedMouse = UnityEngine.InputSystem.Mouse.current; + m_cachedKeyboard = UnityEngine.InputSystem.Keyboard.current; } protected override void Update() @@ -274,6 +285,9 @@ public partial class CECHostPlayer : CECPlayer } m_pWorkMan?.Tick(Time.deltaTime); + // Update cursor based on what's under mouse + EstimateCursor(); + // Update GFXs UpdateGFXs(Time.deltaTime); } @@ -1169,12 +1183,6 @@ public partial class CECHostPlayer : CECPlayer //Debug.LogError("Pos Character = " + pos); } - #region Task - - - - #endregion - private bool NormalAttackObject(int idTarget, bool bForceAttack, bool bMoreClose = false) { if (idTarget == 0 || idTarget == m_PlayerInfo.cid) @@ -2262,10 +2270,11 @@ public partial class CECHostPlayer : CECPlayer if (pObject) { if (m_pHoverGFX.GetState() == GFX_STATE.ST_STOP) + { m_pHoverGFX.Play(); - - m_pSelectedGFX.transform.parent = pObject.transform; - m_pSelectedGFX.transform.localPosition = Vector3.zero; + m_pHoverGFX.transform.parent = pObject.transform; + m_pHoverGFX.transform.localPosition = Vector3.zero; + } } else m_pHoverGFX.Stop(); @@ -2282,11 +2291,11 @@ public partial class CECHostPlayer : CECPlayer if (pObject) { if (m_pSelectedGFX.GetState() == GFX_STATE.ST_STOP) + { m_pSelectedGFX.Play(); - - // m_pSelectedGFX.SetParentTM(pObject.GetAbsoluteTM()); - m_pSelectedGFX.transform.parent = pObject.transform; - m_pSelectedGFX.transform.localPosition = Vector3.zero; + m_pSelectedGFX.transform.parent = pObject.transform; + m_pSelectedGFX.transform.localPosition = Vector3.zero; + } } else m_pSelectedGFX.Stop(); @@ -2364,116 +2373,116 @@ public partial class CECHostPlayer : CECPlayer } // Estimate mouse cursor -private void EstimateCursor() // here -{ - // CECGameRun pGameRun = CECGameRun.Instance; - // - // m_idCurHover = 0; - // if (pGameRun.UIHasCursor() || IsChangingFace()) - // return; - // - // CECCDS pCDS = pGameRun->GetWorld()->GetCDS(); - // CECInputCtrl* pInputCtrl = pGameRun->GetInputCtrl(); - // - // int x, y, iCursor=RES_CUR_NORMAL; - // - // if (CDlgAutoHelp::IsAutoHelp()) - // { - // iCursor = RES_CUR_HAND; - // } - // - // pInputCtrl->GetMousePos(&x, &y); - // A3DVECTOR3 vDest((float)x, (float)y, 1.0f); - // A3DViewport* pView = g_pGame->GetViewport()->GetA3DViewport(); - // pView->InvTransform(vDest, vDest); - // - // A3DVECTOR3 vStart = pView->GetCamera()->GetPos(); - // A3DVECTOR3 vDelta = vDest - vStart; - // - // RAYTRACERT TraceRt; - // int iTraceFlag = TRACEOBJ_LBTNCLICK; - // if (pInputCtrl->KeyIsBeingPressed(VK_SHIFT)) - // iTraceFlag |= 0x80000000; - // - // if (pInputCtrl->KeyIsBeingPressed(VK_MENU)) - // iTraceFlag |= 0x40000000; - // - // - // - // CECPlayerMan* pPlayerMan = g_pGame->GetGameRun()->GetWorld()->GetPlayerMan(); - // CECElsePlayer* pPatePlayer = pPlayerMan->GetMouseOnPateTextPlayer(x,y); - // if (pPatePlayer && pPatePlayer->GetBoothState() == 2){ - // iCursor = RES_CUR_HAND; - // m_idCurHover = pPatePlayer->GetCharacterID(); - // } - // - // if (pCDS->RayTrace(vStart, vDelta, 1.0f, &TraceRt, iTraceFlag, (DWORD)this)) - // { - // int idHitObject(0); - // A3DVECTOR3 hitDis = TraceRt.vHitPos - vStart; - // if(pPatePlayer){ - // A3DVECTOR3 playerPateDis = pPatePlayer->GetPos() - vStart; - // if (hitDis.Magnitude() < playerPateDis.Magnitude()){ - // idHitObject = pCDS->m_RayTraceRt.iObjectID; - // } - // }else{ - // idHitObject = pCDS->m_RayTraceRt.iObjectID; - // } - // if (idHitObject){ - // bool bForceAttack = glb_GetForceAttackFlag(NULL); - // - // if (pCDS->m_RayTraceRt.iEntity == ECENT_MATTER) - // { - // CECMatter* pMatter = pGameRun->GetWorld()->GetMatterMan()->GetMatter(idHitObject); - // if (pMatter) - // { - // if (!pMatter->IsMine()) - // iCursor = RES_CUR_PICKUP; - // else if (CanGatherMatter(pMatter)) - // iCursor = pMatter->IsMonsterSpiritMine() ? RES_CUR_SWALLOW : RES_CUR_DIG; - // } - // - // if (iCursor != RES_CUR_NORMAL) - // m_idCurHover = idHitObject; - // } - // else if (pCDS->m_RayTraceRt.iEntity == ECENT_NPC) - // { - // CECNPC* pNPC = pGameRun->GetWorld()->GetNPCMan()->GetNPC(idHitObject); - // if (pNPC) - // { - // m_idCurHover = idHitObject; - // if (m_idSelTarget == idHitObject && AttackableJudge(idHitObject, bForceAttack) == 1) - // iCursor = RES_CUR_ATTACK; - // else if (pNPC->IsServerNPC()) - // { - // if (!IsInBattle() || InSameBattleCamp(pNPC)) - // iCursor = RES_CUR_TALK; - // } - // } - // } - // else if (pCDS->m_RayTraceRt.iEntity == ECENT_PLAYER) - // { - // CECElsePlayer* pTracePlayer = pGameRun->GetWorld()->GetPlayerMan()->GetElsePlayer(idHitObject); - // m_idCurHover = idHitObject; - // if (m_idSelTarget == idHitObject && AttackableJudge(idHitObject, bForceAttack) == 1) - // iCursor = RES_CUR_ATTACK; - // } - // - // l_fTestDist = vDelta.Magnitude() * TraceRt.fFraction; - // } - // }else{ - // l_fTestDist = -1.0f; - // } - // - // CECNPCMan* pNPCMan = g_pGame->GetGameRun()->GetWorld()->GetNPCMan(); - // CECNPC* pHoverNPC = pNPCMan->GetMouseOnPateTextNPC(x,y); - // if (pHoverNPC){ - // iCursor = RES_CUR_TALK; - // m_idCurHover = pHoverNPC->GetNPCID(); - // } - // - // g_pGame->ChangeCursor(iCursor); -} + private void EstimateCursor() + { + m_cursorUpdateTimer += Time.deltaTime; + if (m_cursorUpdateTimer < CURSOR_UPDATE_INTERVAL) + return; + m_cursorUpdateTimer = 0f; + + // Early exit checks + if (IsChangingFace() || mainCam == null || m_cachedMouse == null) + { + m_idCurHover = 0; + return; + } + + // Get mouse position using cached device + Vector2 mousePosition = m_cachedMouse.position.ReadValue(); + + // Early exit if mouse hasn't moved significantly (2 pixel threshold) + if (Vector2.Distance(mousePosition, m_lastMousePosition) < 2f) + return; + + m_lastMousePosition = mousePosition; + m_idCurHover = 0; + + CursorType cursorType = CursorType.RES_CUR_NORMAL; + + // Check modifier keys using cached keyboard + bool isShiftPressed = m_cachedKeyboard != null && + (m_cachedKeyboard.leftShiftKey.isPressed || m_cachedKeyboard.rightShiftKey.isPressed); + + Ray ray = mainCam.ScreenPointToRay(mousePosition); + RaycastHit hit; + + // You can add a layer mask here to only raycast against specific layers + // LayerMask interactableMask = LayerMask.GetMask("NPC", "Player", "Item"); + // if (Physics.Raycast(ray, out hit, 100f, interactableMask)) + + if (Physics.Raycast(ray, out hit, 1000f)) // Reduced from 1000f to 100f for better performance + { + // Try to get CECObject component (cached lookup) + CECObject hitObject = hit.collider.GetComponent(); + + if (hitObject != null) + { + int idHitObject = CECObject.GetObjectID(hitObject); + + if (idHitObject != 0) + { + bool bForceAttack = isShiftPressed; + + // Check object type and set appropriate cursor + if (GPDataTypeHelper.ISNPCID(idHitObject)) + { + // NPC handling + CECNPC pNPC = EC_ManMessageMono.Instance?._CECNPCMan?.GetNPC(idHitObject); + if (pNPC != null && !pNPC.IsDead()) + { + m_idCurHover = idHitObject; + + if (m_idSelTarget == idHitObject && AttackableJudge(idHitObject, bForceAttack) == 1) + { + cursorType = CursorType.RES_CUR_ATTACK; + } + else if (pNPC.IsServerNPC()) + { + if (!IsInBattle() || InSameBattleCamp(pNPC)) + { + cursorType = CursorType.RES_CUR_TALK; + } + } + } + } + else if (GPDataTypeHelper.ISPLAYERID(idHitObject)) + { + // Player handling + EC_ElsePlayer pPlayer = EC_ManMessageMono.Instance?.GetECManPlayer?.GetPlayer(idHitObject) as EC_ElsePlayer; + if (pPlayer != null) + { + m_idCurHover = idHitObject; + + if (m_idSelTarget == idHitObject && AttackableJudge(idHitObject, bForceAttack) == 1) + { + cursorType = CursorType.RES_CUR_ATTACK; + } + } + } + else if (GPDataTypeHelper.ISMATTERID(idHitObject)) + { + //todo + // BMLogger.LogError($"[EstimateCursor]- GPDataTypeHelper.ISMATTERID: {idHitObject}"); + // Matter/item handling (uncomment when CECMatter is implemented) + // CECMatter pMatter = GetMatterManager()?.GetMatter(idHitObject); + // if (pMatter != null) + // { + // if (!pMatter.IsMine()) + // cursorType = CursorType.Pickup; + // else if (CanGatherMatter(pMatter)) + // cursorType = pMatter.IsMonsterSpiritMine() ? CursorType.Swallow : CursorType.Dig; + // + // if (cursorType != CursorType.Normal) + // m_idCurHover = idHitObject; + // } + } + } + } + } + + // Apply cursor change + EC_Game.ChangeCursor((int)cursorType); + } } public enum StateAnim diff --git a/Assets/Scripts/Utilities/EC_Resource.cs b/Assets/Scripts/Utilities/EC_Resource.cs index f9983e9cea..e45e849346 100644 --- a/Assets/Scripts/Utilities/EC_Resource.cs +++ b/Assets/Scripts/Utilities/EC_Resource.cs @@ -2,21 +2,22 @@ using UnityEngine; namespace BrewMonster { + // Cursor resource + public enum CursorType + { + RES_CUR_NORMAL = 0, + RES_CUR_ATTACK, + RES_CUR_TALK, + RES_CUR_PICKUP, + RES_CUR_REPAIR, + RES_CUR_HAND, + RES_CUR_FLAG, + RES_CUR_DIG, + RES_CUR_SWALLOW, + NUM_RES_CURSOR, + }; public class EC_Resource { - // Cursor resource - static readonly string[] l_aCurFiles = - { - "cursors/normal.ani", - "cursors/attack.cur", - "cursors/talk.cur", - "cursors/pick.cur", - "cursors/repair.cur", - "cursors/hand.cur", - "cursors/flag.cur", - "cursors/dig.ani", - "cursors/gourd.cur", - }; // GFX resource private static readonly string[] l_aGFXFiles = // use where? {