Merge branch 'develop' of https://git.pthub.vn/Unity/perfect-world-unity into fix-ui
This commit is contained in:
@@ -1,5 +1,57 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!1102 &-6682150482281830067
|
||||
AnimatorState:
|
||||
serializedVersion: 6
|
||||
m_ObjectHideFlags: 1
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: "\u6253\u5750_\u901A\u7528"
|
||||
m_Speed: 1
|
||||
m_CycleOffset: 0
|
||||
m_Transitions: []
|
||||
m_StateMachineBehaviours: []
|
||||
m_Position: {x: 50, y: 50, z: 0}
|
||||
m_IKOnFeet: 0
|
||||
m_WriteDefaultValues: 1
|
||||
m_Mirror: 0
|
||||
m_SpeedParameterActive: 0
|
||||
m_MirrorParameterActive: 0
|
||||
m_CycleOffsetParameterActive: 0
|
||||
m_TimeParameterActive: 0
|
||||
m_Motion: {fileID: 7400000, guid: 93519909dda6cca42a0c28127afbbb52, type: 2}
|
||||
m_Tag:
|
||||
m_SpeedParameter:
|
||||
m_MirrorParameter:
|
||||
m_CycleOffsetParameter:
|
||||
m_TimeParameter:
|
||||
--- !u!1102 &-4679316952246346250
|
||||
AnimatorState:
|
||||
serializedVersion: 6
|
||||
m_ObjectHideFlags: 1
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: "\u6253\u5750\u5FAA\u73AF_\u901A\u7528"
|
||||
m_Speed: 1
|
||||
m_CycleOffset: 0
|
||||
m_Transitions: []
|
||||
m_StateMachineBehaviours: []
|
||||
m_Position: {x: 50, y: 50, z: 0}
|
||||
m_IKOnFeet: 0
|
||||
m_WriteDefaultValues: 1
|
||||
m_Mirror: 0
|
||||
m_SpeedParameterActive: 0
|
||||
m_MirrorParameterActive: 0
|
||||
m_CycleOffsetParameterActive: 0
|
||||
m_TimeParameterActive: 0
|
||||
m_Motion: {fileID: 7400000, guid: bf857f5576da777429ed5a6fd606294a, type: 2}
|
||||
m_Tag:
|
||||
m_SpeedParameter:
|
||||
m_MirrorParameter:
|
||||
m_CycleOffsetParameter:
|
||||
m_TimeParameter:
|
||||
--- !u!1107 &-4297166198488271538
|
||||
AnimatorStateMachine:
|
||||
serializedVersion: 6
|
||||
@@ -8,7 +60,13 @@ AnimatorStateMachine:
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: Base Layer
|
||||
m_ChildStates: []
|
||||
m_ChildStates:
|
||||
- serializedVersion: 1
|
||||
m_State: {fileID: -6682150482281830067}
|
||||
m_Position: {x: 330, y: 78, z: 0}
|
||||
- serializedVersion: 1
|
||||
m_State: {fileID: -4679316952246346250}
|
||||
m_Position: {x: 348, y: 166, z: 0}
|
||||
m_ChildStateMachines: []
|
||||
m_AnyStateTransitions: []
|
||||
m_EntryTransitions: []
|
||||
@@ -18,7 +76,7 @@ AnimatorStateMachine:
|
||||
m_EntryPosition: {x: 50, y: 120, z: 0}
|
||||
m_ExitPosition: {x: 800, y: 120, z: 0}
|
||||
m_ParentStateMachinePosition: {x: 800, y: 20, z: 0}
|
||||
m_DefaultState: {fileID: 0}
|
||||
m_DefaultState: {fileID: -6682150482281830067}
|
||||
--- !u!91 &9100000
|
||||
AnimatorController:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -33,25 +91,25 @@ AnimatorController:
|
||||
m_DefaultFloat: 0
|
||||
m_DefaultInt: 0
|
||||
m_DefaultBool: 0
|
||||
m_Controller: {fileID: 0}
|
||||
m_Controller: {fileID: 9100000}
|
||||
- m_Name: IntParam
|
||||
m_Type: 3
|
||||
m_DefaultFloat: 0
|
||||
m_DefaultInt: 0
|
||||
m_DefaultBool: 0
|
||||
m_Controller: {fileID: 0}
|
||||
m_Controller: {fileID: 9100000}
|
||||
- m_Name: BoolParam
|
||||
m_Type: 4
|
||||
m_DefaultFloat: 0
|
||||
m_DefaultInt: 0
|
||||
m_DefaultBool: 0
|
||||
m_Controller: {fileID: 0}
|
||||
m_Controller: {fileID: 9100000}
|
||||
- m_Name: TriggerParam
|
||||
m_Type: 9
|
||||
m_DefaultFloat: 0
|
||||
m_DefaultInt: 0
|
||||
m_DefaultBool: 0
|
||||
m_Controller: {fileID: 0}
|
||||
m_Controller: {fileID: 9100000}
|
||||
m_AnimatorLayers:
|
||||
- serializedVersion: 5
|
||||
m_Name: Base Layer
|
||||
|
||||
@@ -69,7 +69,7 @@ TextureImporter:
|
||||
platformSettings:
|
||||
- serializedVersion: 4
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
maxTextureSize: 512
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
@@ -93,6 +93,45 @@ TextureImporter:
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: Android
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: WebGL
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: WindowsStoreApps
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
|
||||
@@ -69,7 +69,7 @@ TextureImporter:
|
||||
platformSettings:
|
||||
- serializedVersion: 4
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
maxTextureSize: 512
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
@@ -93,6 +93,45 @@ TextureImporter:
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: Android
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: WebGL
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: WindowsStoreApps
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
|
||||
@@ -69,7 +69,7 @@ TextureImporter:
|
||||
platformSettings:
|
||||
- serializedVersion: 4
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
maxTextureSize: 512
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
@@ -106,6 +106,32 @@ TextureImporter:
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: WebGL
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: WindowsStoreApps
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
|
||||
@@ -69,7 +69,7 @@ TextureImporter:
|
||||
platformSettings:
|
||||
- serializedVersion: 4
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
maxTextureSize: 512
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
@@ -106,6 +106,32 @@ TextureImporter:
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: WebGL
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: WindowsStoreApps
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
|
||||
@@ -69,7 +69,7 @@ TextureImporter:
|
||||
platformSettings:
|
||||
- serializedVersion: 4
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
maxTextureSize: 512
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
@@ -106,6 +106,32 @@ TextureImporter:
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: WebGL
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: WindowsStoreApps
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
|
||||
@@ -69,7 +69,7 @@ TextureImporter:
|
||||
platformSettings:
|
||||
- serializedVersion: 4
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
maxTextureSize: 512
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
@@ -106,6 +106,32 @@ TextureImporter:
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: WebGL
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: WindowsStoreApps
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
|
||||
@@ -69,7 +69,7 @@ TextureImporter:
|
||||
platformSettings:
|
||||
- serializedVersion: 4
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
maxTextureSize: 512
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
@@ -106,6 +106,32 @@ TextureImporter:
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: WebGL
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: WindowsStoreApps
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
|
||||
@@ -69,7 +69,7 @@ TextureImporter:
|
||||
platformSettings:
|
||||
- serializedVersion: 4
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
maxTextureSize: 512
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
@@ -106,6 +106,32 @@ TextureImporter:
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: WebGL
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: WindowsStoreApps
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* FILE: CECHPWorkSit.cs
|
||||
*
|
||||
* DESCRIPTION: Host player sit work
|
||||
*
|
||||
* CONVERTED FROM: EC_HPWorkSit.cpp/EC_HPWorkSit.h
|
||||
*/
|
||||
|
||||
using BrewMonster;
|
||||
using CSNetwork.GPDataType;
|
||||
|
||||
namespace BrewMonster.Scripts
|
||||
{
|
||||
public class CECHPWorkSit : CECHPWork
|
||||
{
|
||||
protected bool m_bBeSitting;
|
||||
|
||||
public CECHPWorkSit(CECHPWorkMan pWorkMan) : base(Host_work_ID.WORK_SIT, pWorkMan)
|
||||
{
|
||||
m_dwMask = Work_mask.MASK_SIT;
|
||||
m_dwTransMask = Work_mask.MASK_STAND;
|
||||
Reset();
|
||||
}
|
||||
|
||||
public void SetBeSittingFlag(bool bTrue)
|
||||
{
|
||||
m_bBeSitting = bTrue;
|
||||
}
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
base.Reset();
|
||||
m_bBeSitting = false;
|
||||
}
|
||||
|
||||
public override bool CopyData(CECHPWork pWork)
|
||||
{
|
||||
if (!base.CopyData(pWork))
|
||||
return false;
|
||||
|
||||
CECHPWorkSit pSrc = (CECHPWorkSit)pWork;
|
||||
m_bBeSitting = pSrc.m_bBeSitting;
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override void OnFirstTick()
|
||||
{
|
||||
m_pHost.m_iMoveMode = (int)Move_Mode.MOVE_STAND;
|
||||
if (m_bBeSitting)
|
||||
m_pHost.PlayAction((int)PLAYER_ACTION_TYPE.ACT_SITDOWN_LOOP);
|
||||
else
|
||||
{
|
||||
m_pHost.PlayAction((int)PLAYER_ACTION_TYPE.ACT_SITDOWN);
|
||||
m_pHost.PlayAction((int)PLAYER_ACTION_TYPE.ACT_SITDOWN_LOOP, true, 200, true);
|
||||
}
|
||||
}
|
||||
|
||||
public override bool Tick(float dwDeltaTime)
|
||||
{
|
||||
base.Tick(dwDeltaTime);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d9a9c005284728d428a534fcf337a5b1
|
||||
@@ -649,7 +649,7 @@ namespace BrewMonster.Scripts
|
||||
//case CECHPWork.Host_work_ID.WORK_FOLLOW: pWork = new CECHPWorkFollow(this); break;
|
||||
case CECHPWork.Host_work_ID.WORK_FLYOFF: pWork = new CECHPWorkFly(this); break;
|
||||
case CECHPWork.Host_work_ID.WORK_FREEFALL: pWork = new CECHPWorkFall(this); break;
|
||||
//case CECHPWork.Host_work_ID.WORK_SIT: pWork = new CECHPWorkSit(this); break;
|
||||
case CECHPWork.Host_work_ID.WORK_SIT: pWork = new CECHPWorkSit(this); break;
|
||||
case CECHPWork.Host_work_ID.WORK_PICKUP: pWork = new EC_HPWorkPick(this); break;
|
||||
case CECHPWork.Host_work_ID.WORK_CONCENTRATE: pWork = new CECHPWorkConcentrate(this); break;
|
||||
//case CECHPWork.Host_work_ID.WORK_REVIVE: pWork = new CECHPWorkRevive(this); break;
|
||||
|
||||
@@ -875,11 +875,7 @@ namespace BrewMonster.Scripts
|
||||
|
||||
vCurPos = m_pHost.m_MoveCtrl.GroundMove(m_vCurDir, fSpeed, fDeltaTime, m_pHost.m_fVertSpeed);
|
||||
if (!m_vCurDir.IsZero())
|
||||
{
|
||||
//m_pHost.StartModelMove(m_vCurDir, GPDataTypeHelper.g_vAxisY, 100);
|
||||
//m_pHost.ChangeModelTargetDirAndUp(m_vCurDir, GPDataTypeHelper.g_vAxisY);
|
||||
UpdateFacingFromDelta(vCurPos);
|
||||
}
|
||||
OrientHostHorizontal(m_vCurDir);
|
||||
|
||||
if (m_pHost.m_MoveCtrl.MoveBlocked() >= 3)
|
||||
{
|
||||
|
||||
@@ -343,6 +343,15 @@ namespace PerfectWorld.Scripts.Managers
|
||||
}
|
||||
return best;
|
||||
}
|
||||
|
||||
/// <summary>Port of CECMatterMan::FindMatterNearHost — nearest pickupable ground matter.</summary>
|
||||
public CECMatter FindMatterNearHost(float fRadius, bool bPickOnly = true)
|
||||
{
|
||||
CECHostPlayer host = CECGameRun.Instance?.GetHostPlayer();
|
||||
if (host == null)
|
||||
return null;
|
||||
return GetNearestPickupableMatter(host.GetPos(), fRadius);
|
||||
}
|
||||
|
||||
public CECMatter CreateMatter(info_matter info)
|
||||
{
|
||||
|
||||
@@ -67,6 +67,7 @@ namespace PerfectWorld.Scripts.Managers
|
||||
case EC_MsgDef.MSG_PM_PLAYERDOEMOTE:
|
||||
case EC_MsgDef.MSG_PM_PLAYERGATHER:
|
||||
case EC_MsgDef.MSG_PM_PLAYERFLY:
|
||||
case EC_MsgDef.MSG_PM_PLAYERSITDOWN:
|
||||
case EC_MsgDef.MSG_PM_PLAYERMOUNT:
|
||||
case EC_MsgDef.MSG_PM_PLAYERCHGSHAPE:
|
||||
case EC_MsgDef.MSG_PM_PLAYERSKILLRESULT:
|
||||
@@ -754,6 +755,12 @@ namespace PerfectWorld.Scripts.Managers
|
||||
cid = (GPDataTypeHelper.FromBytes<cmd_object_landing>((byte[])Msg.dwParam1)).object_id;
|
||||
|
||||
break;
|
||||
case EC_MsgDef.MSG_PM_PLAYERSITDOWN:
|
||||
if (Convert.ToInt32(Msg.dwParam2) == CommandID.OBJECT_SIT_DOWN)
|
||||
cid = GPDataTypeHelper.FromBytes<cmd_object_sit_down>((byte[])Msg.dwParam1).id;
|
||||
else
|
||||
cid = GPDataTypeHelper.FromBytes<cmd_object_stand_up>((byte[])Msg.dwParam1).id;
|
||||
break;
|
||||
case EC_MsgDef.MSG_PM_PLAYERMOUNT:
|
||||
cid = (GPDataTypeHelper.FromBytes<cmd_player_mounting>((byte[])Msg.dwParam1)).id;
|
||||
break;
|
||||
|
||||
@@ -3,76 +3,59 @@ using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
// Filename : CMoveAgent.cs
|
||||
// Creator : ported/simplified from C++ (AutoPFImp/AutoMoveImp/MoveAgent.*)
|
||||
// Creator : ported from C++ (AutoPFImp/AutoMoveImp/MoveAgent.*)
|
||||
// Date : 2026/01/09
|
||||
|
||||
namespace AutoMove
|
||||
{
|
||||
/// <summary>
|
||||
/// Minimal MoveAgent: loads movemap and provides A* path on layer0 rmap.
|
||||
/// 最小 MoveAgent:加载 movemap,并在第0层 rmap 上执行 A* 路径搜索。
|
||||
/// MoveAgent: A* on layer0 rmap + COptimizePath (matches C++ CMoveAgent flow).
|
||||
/// </summary>
|
||||
public class CMoveAgent
|
||||
{
|
||||
// Debug switch (enable temporarily while validating routes).
|
||||
// 调试开关(验证寻路时可临时开启)。
|
||||
// NOTE: must not be const, otherwise Unity compiler warns about unreachable code.
|
||||
// 注意:不要用 const,否则 Unity 编译会报“不可达代码”警告。
|
||||
private static bool DEBUG_AUTOPF = false;
|
||||
|
||||
public abstract class BrushTest
|
||||
{
|
||||
// from.y/to.y store DH in original engine.
|
||||
// 原版中 from.y/to.y 存储 DH(相对地形高度差)。
|
||||
public abstract bool Collide(Vector3 from, Vector3 to);
|
||||
}
|
||||
|
||||
private readonly CMoveMap m_pMoveMap = new CMoveMap();
|
||||
private Vector3 m_vOriginOverride;
|
||||
private COptimizePath m_pPathOptimizer;
|
||||
|
||||
private Vector2Int m_ptStart;
|
||||
private Vector2Int m_ptGoal;
|
||||
private int m_iLayerStart;
|
||||
private int m_iLayerGoal;
|
||||
|
||||
private readonly List<Vector3> m_path3D = new List<Vector3>(1024);
|
||||
|
||||
public bool Load(string basePathNoExt, Func<string, byte[]> resolver, Vector3? originOverride)
|
||||
{
|
||||
// basePathNoExt corresponds to "maps\\<map>\\movemap\\r.._..-c.._..-l0" in C++.
|
||||
// basePathNoExt 对应 C++ 的 "maps\\<map>\\movemap\\r.._..-c.._..-l0"。
|
||||
string cfgName = basePathNoExt;
|
||||
if (!cfgName.EndsWith(".cfg", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
cfgName += ".cfg";
|
||||
}
|
||||
|
||||
byte[] cfgBytes = resolver(cfgName);
|
||||
if (cfgBytes == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Resolver for referenced files: in cfg, references are baseName + ".prmap" etc.
|
||||
// cfg 内引用:baseName + ".prmap" 等。
|
||||
bool ok = m_pMoveMap.Load(cfgBytes, resolver, basePathNoExt);
|
||||
if (!ok)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (originOverride.HasValue)
|
||||
{
|
||||
m_vOriginOverride = originOverride.Value;
|
||||
m_pMoveMap.SetOrigin(m_vOriginOverride);
|
||||
}
|
||||
m_pMoveMap.SetOrigin(originOverride.Value);
|
||||
|
||||
CreateOptimizer();
|
||||
return true;
|
||||
}
|
||||
|
||||
void CreateOptimizer()
|
||||
{
|
||||
m_pPathOptimizer = new COptimizePath();
|
||||
}
|
||||
|
||||
public bool IsReady()
|
||||
{
|
||||
// Original C++ requires MultiCluGraph; here we only require layer0 RMap.
|
||||
// 原版 C++ 依赖 MultiCluGraph;这里最小实现只要求第0层 RMap。
|
||||
var layer0 = m_pMoveMap.GetLayer(0);
|
||||
return layer0 != null && layer0.GetRMap() != null;
|
||||
}
|
||||
@@ -98,8 +81,6 @@ namespace AutoMove
|
||||
|
||||
public int WhichLayer(Vector3 vWld, float dH, out float layerDist)
|
||||
{
|
||||
// Minimal: single layer 0 if passable.
|
||||
// 最小实现:如果可通行则使用单层0。
|
||||
layerDist = 0.0f;
|
||||
var pt = TransWld2Map(vWld);
|
||||
var layer0 = m_pMoveMap.GetLayer(0);
|
||||
@@ -116,31 +97,72 @@ namespace AutoMove
|
||||
return true;
|
||||
}
|
||||
|
||||
public int GetPathCount() => m_path3D.Count;
|
||||
public List<PathNode> Get2DPath()
|
||||
{
|
||||
return m_pPathOptimizer?.GetPath();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Matches C++ CMoveAgent::GetOptimizeCatchCount — lookahead window for path following.
|
||||
/// 对应 C++:无 PathOptimizer 时为 0,FindNearest/Farthest 仅在单步索引上工作。
|
||||
/// </summary>
|
||||
public int GetOptimizeCatchCount() => 0;
|
||||
public int GetPathCount()
|
||||
{
|
||||
if (m_pPathOptimizer != null)
|
||||
{
|
||||
var path = m_pPathOptimizer.GetPath();
|
||||
if (path != null)
|
||||
return path.Count;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int GetOptimizeCatchCount()
|
||||
{
|
||||
return m_pPathOptimizer != null ? m_pPathOptimizer.GetCatchCount() : 0;
|
||||
}
|
||||
|
||||
public Vector3 Get2DPathNode(int index)
|
||||
{
|
||||
var path2d = Get2DPath();
|
||||
if (path2d == null || index < 0 || index >= path2d.Count)
|
||||
return Vector3.zero;
|
||||
PathNode pathNode = path2d[index];
|
||||
Vector2 ptWld = m_pMoveMap.TransMap2Wld(pathNode.ptMap.x, pathNode.ptMap.y);
|
||||
return new Vector3(ptWld.x, 0f, ptWld.y);
|
||||
}
|
||||
|
||||
public Vector3 Get3DPathNode(int index)
|
||||
{
|
||||
if (index < 0 || index >= m_path3D.Count) return Vector3.zero;
|
||||
return m_path3D[index];
|
||||
var path2d = Get2DPath();
|
||||
if (path2d == null || index < 0 || index >= path2d.Count)
|
||||
return Vector3.zero;
|
||||
PathNode pathNode = path2d[index];
|
||||
Vector2 ptWld = m_pMoveMap.TransMap2Wld(pathNode.ptMap.x, pathNode.ptMap.y);
|
||||
float dh = m_pMoveMap.GetDH(pathNode.layer, (int)pathNode.ptMap.x, (int)pathNode.ptMap.y);
|
||||
return new Vector3(ptWld.x, dh, ptWld.y);
|
||||
}
|
||||
|
||||
public System.Collections.Generic.List<Vector3> GetFullPath()
|
||||
/// <summary>Ported from C++ CMoveAgent::Optimize.</summary>
|
||||
public bool Optimize(int moveIndex)
|
||||
{
|
||||
return new System.Collections.Generic.List<Vector3>(m_path3D);
|
||||
if (m_pPathOptimizer == null)
|
||||
return false;
|
||||
if (!m_pPathOptimizer.NeedOptimize(moveIndex))
|
||||
return false;
|
||||
m_pPathOptimizer.StepOptimize();
|
||||
return true;
|
||||
}
|
||||
|
||||
public List<Vector3> GetFullPath()
|
||||
{
|
||||
var path = new List<Vector3>();
|
||||
var path2d = Get2DPath();
|
||||
if (path2d == null)
|
||||
return path;
|
||||
for (int i = 0; i < path2d.Count; i++)
|
||||
path.Add(Get2DPathNode(i));
|
||||
return path;
|
||||
}
|
||||
|
||||
public bool Search(int nMaxExpand = -1)
|
||||
{
|
||||
// A* on layer0 rmap
|
||||
// 在第0层 rmap 上执行 A*
|
||||
m_path3D.Clear();
|
||||
|
||||
var layer0 = m_pMoveMap.GetLayer(0);
|
||||
var rmap = layer0?.GetRMap();
|
||||
if (rmap == null) return false;
|
||||
@@ -149,30 +171,18 @@ namespace AutoMove
|
||||
if (w <= 0 || h <= 0) return false;
|
||||
|
||||
if (!InBounds(m_ptStart, w, h) || !InBounds(m_ptGoal, w, h))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// If goal or start is not passable, try to find nearest passable (original MoveAgent does this).
|
||||
// 如果起点或终点不可通行,尝试寻找最近可通行点(原版 MoveAgent 会这样做)。
|
||||
if (!rmap.GetPixel(m_ptStart.x, m_ptStart.y))
|
||||
{
|
||||
if (!TryFindNearestPassable(rmap, m_ptStart, w, h, 64, out var newStart))
|
||||
{
|
||||
if (DEBUG_AUTOPF) Debug.LogWarning($"[CMoveAgent] start not passable and no nearest passable found. start={m_ptStart}");
|
||||
return false;
|
||||
}
|
||||
if (DEBUG_AUTOPF) Debug.Log($"[CMoveAgent] Adjust start {m_ptStart} -> {newStart}");
|
||||
m_ptStart = newStart;
|
||||
}
|
||||
if (!rmap.GetPixel(m_ptGoal.x, m_ptGoal.y))
|
||||
{
|
||||
if (!TryFindNearestPassable(rmap, m_ptGoal, w, h, 64, out var newGoal))
|
||||
{
|
||||
if (DEBUG_AUTOPF) Debug.LogWarning($"[CMoveAgent] goal not passable and no nearest passable found. goal={m_ptGoal}");
|
||||
return false;
|
||||
}
|
||||
if (DEBUG_AUTOPF) Debug.Log($"[CMoveAgent] Adjust goal {m_ptGoal} -> {newGoal}");
|
||||
m_ptGoal = newGoal;
|
||||
}
|
||||
|
||||
@@ -184,8 +194,6 @@ namespace AutoMove
|
||||
open.Push(m_ptStart, Heuristic(m_ptStart, m_ptGoal));
|
||||
|
||||
int expands = 0;
|
||||
//ToDo: need use another method to caculate the value of maxExpand
|
||||
//800000 is a magic number, need to be optimized
|
||||
int maxExpand = nMaxExpand > 0 ? nMaxExpand : 800000;
|
||||
|
||||
while (open.Count > 0 && expands < maxExpand)
|
||||
@@ -228,16 +236,12 @@ namespace AutoMove
|
||||
|
||||
if (rmap == null) return false;
|
||||
|
||||
// Check origin first
|
||||
// 先检查原点
|
||||
if (origin.x >= 0 && origin.x < w && origin.y >= 0 && origin.y < h && rmap.GetPixel(origin.x, origin.y))
|
||||
{
|
||||
best = origin;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Expand square rings
|
||||
// 按方形“圈”扩展搜索
|
||||
for (int r = 1; r <= maxRadius; r++)
|
||||
{
|
||||
int minX = Math.Max(0, origin.x - r);
|
||||
@@ -245,14 +249,11 @@ namespace AutoMove
|
||||
int minY = Math.Max(0, origin.y - r);
|
||||
int maxY = Math.Min(h - 1, origin.y + r);
|
||||
|
||||
// Top/bottom edges
|
||||
for (int x = minX; x <= maxX; x++)
|
||||
{
|
||||
TryConsider(x, minY);
|
||||
TryConsider(x, maxY);
|
||||
}
|
||||
|
||||
// Left/right edges (excluding corners already checked)
|
||||
for (int y = minY + 1; y <= maxY - 1; y++)
|
||||
{
|
||||
TryConsider(minX, y);
|
||||
@@ -285,28 +286,35 @@ namespace AutoMove
|
||||
|
||||
private void ReconstructPath(Dictionary<Vector2Int, Vector2Int> cameFrom, Vector2Int cur)
|
||||
{
|
||||
List<Vector2Int> rev = new List<Vector2Int>(1024) { cur };
|
||||
var rev = new List<Vector2Int>(1024) { cur };
|
||||
while (cameFrom.TryGetValue(cur, out var prev))
|
||||
{
|
||||
cur = prev;
|
||||
rev.Add(cur);
|
||||
}
|
||||
|
||||
rev.Reverse();
|
||||
// Convert to world positions (y will be resolved by host terrain in movement).
|
||||
// 转为世界坐标(y 由移动逻辑/地形解析)。
|
||||
|
||||
var initPath = new List<PathNode>(rev.Count);
|
||||
for (int i = 0; i < rev.Count; i++)
|
||||
{
|
||||
m_path3D.Add(Map2Wld(rev[i]));
|
||||
initPath.Add(new PathNode
|
||||
{
|
||||
ptMap = new Vector2(rev[i].x, rev[i].y),
|
||||
layer = m_iLayerStart,
|
||||
});
|
||||
}
|
||||
|
||||
if (m_pPathOptimizer == null)
|
||||
CreateOptimizer();
|
||||
|
||||
// C++: m_pPathOptimizer->SetupOptimize(GetMoveMap(), path);
|
||||
m_pPathOptimizer.SetupOptimize(m_pMoveMap, initPath);
|
||||
}
|
||||
|
||||
private static bool InBounds(Vector2Int p, int w, int h) => p.x >= 0 && p.x < w && p.y >= 0 && p.y < h;
|
||||
|
||||
private static int Heuristic(Vector2Int a, Vector2Int b)
|
||||
{
|
||||
// Octile distance * 10
|
||||
// 八方向启发式(octile)*10
|
||||
int dx = Mathf.Abs(a.x - b.x);
|
||||
int dy = Mathf.Abs(a.y - b.y);
|
||||
int min = Math.Min(dx, dy);
|
||||
@@ -316,8 +324,6 @@ namespace AutoMove
|
||||
|
||||
private static int Cost(Vector2Int a, Vector2Int b)
|
||||
{
|
||||
// Diagonal=14, straight=10
|
||||
// 斜向=14,直向=10
|
||||
int dx = Mathf.Abs(a.x - b.x);
|
||||
int dy = Mathf.Abs(a.y - b.y);
|
||||
return (dx + dy == 2) ? 14 : 10;
|
||||
@@ -337,33 +343,13 @@ namespace AutoMove
|
||||
|
||||
public void ResetSearch()
|
||||
{
|
||||
// Çå³ýµ±Ç°ËÑË÷״̬
|
||||
//if (m_iStat == PF_STATE_UNKNOWN)
|
||||
//{
|
||||
// return;
|
||||
//}
|
||||
//if (m_pPfAlg)
|
||||
//{
|
||||
// m_pPfAlg->Reset();
|
||||
//}
|
||||
//if (m_pPathOptimizer)
|
||||
//{
|
||||
// m_pPathOptimizer.Reset();
|
||||
//}
|
||||
m_ptStart.x = m_ptStart.y = 0;
|
||||
m_ptStart = Vector2Int.zero;
|
||||
m_iLayerStart = -1;
|
||||
m_ptGoal.x = m_ptGoal.y = 0;
|
||||
m_ptGoal = Vector2Int.zero;
|
||||
m_iLayerGoal = -1;
|
||||
//m_pBrushTest = null;
|
||||
|
||||
//m_iStat = PF_STATE_UNKNOWN;
|
||||
m_path3D.Clear();
|
||||
m_pPathOptimizer?.Reset();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Very small min-heap for A*.
|
||||
/// A* 用的小型最小堆。
|
||||
/// </summary>
|
||||
private sealed class MinHeap
|
||||
{
|
||||
private struct Node
|
||||
@@ -419,5 +405,3 @@ namespace AutoMove
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -56,8 +56,13 @@ namespace AutoMove
|
||||
|
||||
public Vector2 TransMap2Wld(int x, int y)
|
||||
{
|
||||
float wx = m_vOrigin.x + (x + 0.5f) * m_fPixelSize;
|
||||
float wz = m_vOrigin.z + (y + 0.5f) * m_fPixelSize;
|
||||
return TransMap2Wld((float)x, (float)y);
|
||||
}
|
||||
|
||||
public Vector2 TransMap2Wld(float mapX, float mapY)
|
||||
{
|
||||
float wx = m_vOrigin.x + (mapX + 0.5f) * m_fPixelSize;
|
||||
float wz = m_vOrigin.z + (mapY + 0.5f) * m_fPixelSize;
|
||||
return new Vector2(wx, wz);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,298 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
// Ported from C++ OptimizePath.h / OptimizePath.cpp (Kui Wu, 2007).
|
||||
|
||||
namespace AutoMove
|
||||
{
|
||||
/// <summary>Line sampler for map-space path optimization (C++ CLine).</summary>
|
||||
sealed class CLine
|
||||
{
|
||||
Vector2 m_from;
|
||||
Vector2 m_dir;
|
||||
int m_count;
|
||||
|
||||
public void Init(Vector2 from, Vector2 dir)
|
||||
{
|
||||
m_from = from;
|
||||
m_dir = dir;
|
||||
float len = m_dir.magnitude;
|
||||
if (len > 1e-8f)
|
||||
{
|
||||
m_dir.x /= len;
|
||||
m_dir.y /= len;
|
||||
}
|
||||
m_count = 0;
|
||||
}
|
||||
|
||||
public void Init(Vector2 from, int dirX, int dirY)
|
||||
{
|
||||
Init(from, new Vector2(dirX, dirY));
|
||||
}
|
||||
|
||||
public Vector2 Next()
|
||||
{
|
||||
m_count++;
|
||||
return new Vector2(m_from.x + m_dir.x * m_count, m_from.y + m_dir.y * m_count);
|
||||
}
|
||||
|
||||
public int GetCount() => m_count;
|
||||
public Vector2 GetFrom() => m_from;
|
||||
public void Reset() => m_count = 0;
|
||||
}
|
||||
|
||||
/// <summary>Path optimizer — port of C++ COptimizePath.</summary>
|
||||
public sealed class COptimizePath
|
||||
{
|
||||
const int LookAhead = 60;
|
||||
const int LookStep = 3;
|
||||
|
||||
CMoveMap m_pMoveMap;
|
||||
int m_mapWidth;
|
||||
int m_mapHeight;
|
||||
readonly Dictionary<int, short> m_lookUp = new Dictionary<int, short>(4096);
|
||||
readonly List<PathNode> m_path = new List<PathNode>(1024);
|
||||
int m_curIndex = -1;
|
||||
int m_catchCount = 10;
|
||||
int m_curLayer = -1;
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
m_pMoveMap = null;
|
||||
m_mapWidth = 0;
|
||||
m_mapHeight = 0;
|
||||
m_lookUp.Clear();
|
||||
m_path.Clear();
|
||||
m_curIndex = -1;
|
||||
m_curLayer = -1;
|
||||
}
|
||||
|
||||
public int GetCatchCount() => m_catchCount;
|
||||
|
||||
public List<PathNode> GetPath() => m_path;
|
||||
|
||||
public bool NeedOptimize(int moveIndex)
|
||||
{
|
||||
if (m_curIndex < m_path.Count
|
||||
&& moveIndex < m_path.Count
|
||||
&& m_curIndex - moveIndex < m_catchCount)
|
||||
{
|
||||
if (moveIndex > m_curIndex)
|
||||
{
|
||||
SetFootprintRange(m_curIndex, moveIndex - 1, 0);
|
||||
m_curIndex = moveIndex;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void SetupOptimize(CMoveMap pMoveMap, List<PathNode> initPath, int catchCount = 10)
|
||||
{
|
||||
m_path.Clear();
|
||||
if (initPath != null && initPath.Count > 0)
|
||||
m_path.AddRange(initPath);
|
||||
|
||||
m_pMoveMap = pMoveMap;
|
||||
m_mapWidth = pMoveMap != null ? pMoveMap.GetMapWidth() : 0;
|
||||
m_mapHeight = pMoveMap != null ? pMoveMap.GetMapLength() : 0;
|
||||
m_curIndex = 0;
|
||||
m_catchCount = catchCount;
|
||||
m_curLayer = -1;
|
||||
|
||||
if (m_path.Count == 0)
|
||||
return;
|
||||
|
||||
CheckLayer();
|
||||
}
|
||||
|
||||
public void StepOptimize()
|
||||
{
|
||||
CheckLayer();
|
||||
int step = m_catchCount * 2;
|
||||
if (step <= 0)
|
||||
return;
|
||||
|
||||
int i = 0;
|
||||
while (i < step && m_curIndex < m_path.Count)
|
||||
{
|
||||
LocalOptimize();
|
||||
i++;
|
||||
m_curIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
void CheckLayer()
|
||||
{
|
||||
if (m_path.Count == 0 || m_curIndex < 0 || m_curIndex >= m_path.Count)
|
||||
return;
|
||||
|
||||
if (m_path[m_curIndex].layer == m_curLayer)
|
||||
return;
|
||||
|
||||
m_curLayer = m_path[m_curIndex].layer;
|
||||
m_lookUp.Clear();
|
||||
|
||||
int i = m_curIndex;
|
||||
while (i < m_path.Count && m_path[i].layer == m_curLayer)
|
||||
{
|
||||
SetFootprint(m_path[i].ptMap, (short)(i + 1));
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
void LocalOptimize()
|
||||
{
|
||||
int toIndex = Mathf.Min(m_curIndex + LookAhead, m_path.Count - 1);
|
||||
var line = new CLine();
|
||||
Vector2 dir;
|
||||
int newCount = -1;
|
||||
|
||||
while (toIndex - m_curIndex > LookStep)
|
||||
{
|
||||
if (GetFootprint(m_path[toIndex].ptMap) == 0)
|
||||
{
|
||||
toIndex -= LookStep;
|
||||
continue;
|
||||
}
|
||||
if (m_path[toIndex].layer != m_curLayer)
|
||||
{
|
||||
toIndex -= LookStep;
|
||||
continue;
|
||||
}
|
||||
|
||||
dir = m_path[toIndex].ptMap - m_path[m_curIndex].ptMap;
|
||||
if ((int)dir.x == 0 && (int)dir.y == 0)
|
||||
{
|
||||
PathIntersect(toIndex);
|
||||
return;
|
||||
}
|
||||
|
||||
line.Init(m_path[m_curIndex].ptMap, dir);
|
||||
if (LineTo(line, m_path[toIndex].ptMap))
|
||||
{
|
||||
newCount = line.GetCount();
|
||||
break;
|
||||
}
|
||||
toIndex -= LookStep;
|
||||
}
|
||||
|
||||
if (newCount > 0)
|
||||
{
|
||||
line.Reset();
|
||||
AddPathPortion(line, toIndex - m_curIndex, newCount);
|
||||
}
|
||||
}
|
||||
|
||||
CBitImage GetRMap(int layer)
|
||||
{
|
||||
if (m_pMoveMap == null)
|
||||
return null;
|
||||
var layerMap = m_pMoveMap.GetLayer(layer);
|
||||
return layerMap?.GetRMap();
|
||||
}
|
||||
|
||||
bool LineTo(CLine line, Vector2 to)
|
||||
{
|
||||
int toX = (int)to.x;
|
||||
int toY = (int)to.y;
|
||||
int curX = (int)line.GetFrom().x;
|
||||
int curY = (int)line.GetFrom().y;
|
||||
|
||||
CBitImage pRMap = GetRMap(m_curLayer);
|
||||
if (pRMap == null)
|
||||
return false;
|
||||
|
||||
int lastX = curX;
|
||||
int lastY = curY;
|
||||
|
||||
while (curX != toX || curY != toY)
|
||||
{
|
||||
Vector2 cur = line.Next();
|
||||
curX = (int)cur.x;
|
||||
curY = (int)cur.y;
|
||||
|
||||
if (!pRMap.GetPixel(curX, curY))
|
||||
return false;
|
||||
|
||||
bool bNeighbor1 = pRMap.GetPixel(lastX, curY);
|
||||
bool bNeighbor2 = pRMap.GetPixel(curX, lastY);
|
||||
|
||||
if (toX == lastX && toY == curY)
|
||||
break;
|
||||
if (toX == curX && toY == lastY)
|
||||
break;
|
||||
|
||||
if (curX != lastX && curY != lastY && (!bNeighbor1 || !bNeighbor2))
|
||||
return false;
|
||||
|
||||
lastX = curX;
|
||||
lastY = curY;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void PathIntersect(int toIndex)
|
||||
{
|
||||
SetFootprintRange(m_curIndex + 1, toIndex, 0);
|
||||
int removeCount = toIndex - m_curIndex;
|
||||
if (removeCount > 0 && m_curIndex + 1 < m_path.Count)
|
||||
m_path.RemoveRange(m_curIndex + 1, removeCount);
|
||||
}
|
||||
|
||||
void AddPathPortion(CLine line, int oldCount, int newCount)
|
||||
{
|
||||
SetFootprintRange(m_curIndex + 1, m_curIndex + oldCount, 0);
|
||||
|
||||
if (oldCount > newCount)
|
||||
{
|
||||
m_path.RemoveRange(m_curIndex + 1, oldCount - newCount);
|
||||
}
|
||||
else if (oldCount < newCount)
|
||||
{
|
||||
int insertCount = newCount - oldCount;
|
||||
for (int k = 0; k < insertCount; k++)
|
||||
m_path.Insert(m_curIndex + 1, new PathNode());
|
||||
}
|
||||
|
||||
int index = m_curIndex + 1;
|
||||
while (line.GetCount() < newCount && index < m_path.Count)
|
||||
{
|
||||
var node = m_path[index];
|
||||
node.ptMap = line.Next();
|
||||
node.layer = m_curLayer;
|
||||
m_path[index] = node;
|
||||
index++;
|
||||
}
|
||||
|
||||
SetFootprintRange(m_curIndex + 1, m_curIndex + newCount, 1);
|
||||
}
|
||||
|
||||
int GetLookUpKey(int x, int y) => y * m_mapWidth + x;
|
||||
|
||||
int GetFootprint(int x, int y)
|
||||
{
|
||||
return m_lookUp.TryGetValue(GetLookUpKey(x, y), out short v) ? v : 0;
|
||||
}
|
||||
|
||||
int GetFootprint(Vector2 pt) => GetFootprint((int)pt.x, (int)pt.y);
|
||||
|
||||
void SetFootprint(int x, int y, int val)
|
||||
{
|
||||
int key = GetLookUpKey(x, y);
|
||||
if (val == 0)
|
||||
m_lookUp.Remove(key);
|
||||
else
|
||||
m_lookUp[key] = (short)val;
|
||||
}
|
||||
|
||||
void SetFootprint(Vector2 pt, int val) => SetFootprint((int)pt.x, (int)pt.y, val);
|
||||
|
||||
void SetFootprintRange(int fromIndex, int toIndex, int val)
|
||||
{
|
||||
for (int i = fromIndex; i <= toIndex && i < m_path.Count; ++i)
|
||||
SetFootprint(m_path[i].ptMap, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 96e45cded56a0bc4188f329f2cf3b676
|
||||
@@ -0,0 +1,22 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace AutoMove
|
||||
{
|
||||
/// <summary>Matches C++ AutoMove::PathNode (PfConstant.h).</summary>
|
||||
public struct PathNode
|
||||
{
|
||||
public Vector2 ptMap;
|
||||
public int layer;
|
||||
|
||||
public Vector2Int GetPtI()
|
||||
{
|
||||
return new Vector2Int(Mathf.FloorToInt(ptMap.x), Mathf.FloorToInt(ptMap.y));
|
||||
}
|
||||
|
||||
public void SetI(Vector2Int pt, int iLayer)
|
||||
{
|
||||
ptMap = new Vector2(pt.x, pt.y);
|
||||
layer = iLayer;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 98c1e0dc325b8e64bbda287a0128aeed
|
||||
@@ -19,7 +19,7 @@ namespace BrewMonster.Scripts
|
||||
/// </summary>
|
||||
public sealed class CECIntelligentRoute
|
||||
{
|
||||
private const bool DEBUG_AUTOPF = true;
|
||||
private const bool DEBUG_AUTOPF = false;
|
||||
/// <summary>cos(5°) for FindFarthestNode — same as C++ EC_IntelligentRoute.cpp.</summary>
|
||||
private static readonly float s_cos5Deg = Mathf.Cos(5f * Mathf.PI / 180f);
|
||||
public enum SearchResult
|
||||
@@ -376,9 +376,22 @@ namespace BrewMonster.Scripts
|
||||
|
||||
// Determine layers (minimal: layer0 or invalid).
|
||||
// 确定层(最小实现:层0或无效)。
|
||||
float startDh = 0f;
|
||||
float endDh = 0f;
|
||||
var world = EC_Game.GetGameRun()?.GetWorld();
|
||||
if (world != null)
|
||||
{
|
||||
A3DVECTOR3 n = GPDataTypeHelper.g_vAxisY;
|
||||
if (world.TryGetTerrainHeight(start, ref n, out float startTer))
|
||||
startDh = start.y - startTer;
|
||||
n = GPDataTypeHelper.g_vAxisY;
|
||||
if (world.TryGetTerrainHeight(end, ref n, out float endTer))
|
||||
endDh = end.y - endTer;
|
||||
}
|
||||
|
||||
float dist;
|
||||
int startLayer = agent.WhichLayer(new Vector3(start.x, start.y, start.z), 0.0f, out dist);
|
||||
int endLayer = agent.WhichLayer(new Vector3(end.x, end.y, end.z), 0.0f, out dist);
|
||||
int startLayer = agent.WhichLayer(new Vector3(start.x, start.y, start.z), startDh, out dist);
|
||||
int endLayer = agent.WhichLayer(new Vector3(end.x, end.y, end.z), endDh, out dist);
|
||||
if (startLayer < 0) startLayer = 0;
|
||||
if (endLayer < 0) endLayer = 0;
|
||||
|
||||
@@ -466,7 +479,8 @@ namespace BrewMonster.Scripts
|
||||
|
||||
m_iCurDest = FindNextNode(pos, m_iCurDest + 1);
|
||||
m_dist2CurDest = (GetCurDest() - pos).MagnitudeH();
|
||||
// C++ calls agent->Optimize(m_iCurDest) here; Unity CMoveAgent has no path optimizer yet.
|
||||
agent.Optimize(m_iCurDest);
|
||||
m_dist2CurDest = (GetCurDest() - pos).MagnitudeH();
|
||||
}
|
||||
|
||||
A3DVECTOR3 GetNodePos(int iNode)
|
||||
@@ -489,17 +503,26 @@ namespace BrewMonster.Scripts
|
||||
if (agent == null)
|
||||
return new A3DVECTOR3(0f, 0f, 0f);
|
||||
Vector3 v = agent.Get3DPathNode(iNode);
|
||||
// C++ adds GetTerrainHeight to Y; Unity path nodes use movemap/world height from loader.
|
||||
return new A3DVECTOR3(v.x, v.y, v.z);
|
||||
var pos = new A3DVECTOR3(v.x, v.y, v.z);
|
||||
var world = EC_Game.GetGameRun()?.GetWorld();
|
||||
if (world != null)
|
||||
{
|
||||
A3DVECTOR3 n = GPDataTypeHelper.g_vAxisY;
|
||||
if (world.TryGetTerrainHeight(pos, ref n, out float terY))
|
||||
pos.y = terY;
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
|
||||
A3DVECTOR3 GetNodePosXZ(int iNode)
|
||||
{
|
||||
if (IsIdle())
|
||||
return new A3DVECTOR3(0f, 0f, 0f);
|
||||
A3DVECTOR3 p = GetNodePosNoCheck(iNode);
|
||||
p.y = 0f;
|
||||
return p;
|
||||
RangedMoveAgent? pCurAgent = GetCurAgent();
|
||||
if (pCurAgent == null || pCurAgent.Value.agent == null)
|
||||
return new A3DVECTOR3(0f, 0f, 0f);
|
||||
Vector3 v = pCurAgent.Value.agent.Get2DPathNode(iNode);
|
||||
return new A3DVECTOR3(v.x, v.y, v.z);
|
||||
}
|
||||
|
||||
int FindNearestNode(A3DVECTOR3 curPos, int iNodeFrom)
|
||||
|
||||
@@ -1545,21 +1545,21 @@ namespace BrewMonster
|
||||
szAct= $"{action.data.ActionPrefix}_{action.data.action_weapon_suffix[weapon_type].Suffix}";
|
||||
|
||||
|
||||
// CECModel pRightHandWeapon = GetRightHandWeapon();
|
||||
// if( !bQueue )
|
||||
// {
|
||||
// PlayNonSkillActionWithName(iAction, szAct, bRestart, iTransTime);
|
||||
CECModel pRightHandWeapon = GetRightHandWeapon();
|
||||
if( !bQueue )
|
||||
{
|
||||
m_pActionController. PlayNonSkillActionWithName(iAction, szAct, bRestart, iTransTime);
|
||||
|
||||
// if(pRightHandWeapon && IsUsingMagicWeapon())
|
||||
// pRightHandWeapon->PlayActionByName(_GenWeaponActionName(szAct, m_iGender), 1.0f, bRestart, iTransTime, true, iAction);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// QueueNonSkillActionWithName(iAction, szAct, iTransTime, bRestart, false, false, true, NULL, COMACT_FLAG_MODE_ONCE_MULTIIGNOREGFX);
|
||||
// if(pRightHandWeapon && IsUsingMagicWeapon())
|
||||
// pRightHandWeapon->PlayActionByName(_GenWeaponActionName(szAct, m_iGender), 1.0f, bRestart, iTransTime, true, iAction);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pActionController. QueueNonSkillActionWithName(iAction, szAct, iTransTime, bRestart, false, false, true, null, COMACT_FLAG_MODE_ONCE_MULTIIGNOREGFX);
|
||||
|
||||
// if(pRightHandWeapon && IsUsingMagicWeapon())
|
||||
// pRightHandWeapon->QueueAction(_GenWeaponActionName(szAct, m_iGender), iTransTime, iAction, bRestart ? true : false);
|
||||
// }
|
||||
// if(pRightHandWeapon && IsUsingMagicWeapon())
|
||||
// pRightHandWeapon->QueueAction(_GenWeaponActionName(szAct, m_iGender), iTransTime, iAction, bRestart ? true : false);
|
||||
}
|
||||
|
||||
if (m_iBuddyId != 0)
|
||||
{
|
||||
@@ -1620,7 +1620,7 @@ namespace BrewMonster
|
||||
// UpdateWeaponHangerPosByAction(iAction);
|
||||
// }
|
||||
// EventBus.PublishChannel(m_PlayerInfo.cid, new PlayActionEvent(szShapeName, szAct, iTransTime));
|
||||
m_pActionController.PlayNonSkillActionWithName(iAction, szAct, bRestart, iTransTime);
|
||||
// m_pActionController.PlayNonSkillActionWithName(iAction, szAct, bRestart, iTransTime);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
|
||||
@@ -151,6 +151,59 @@ public class NPCVisual : MonoBehaviour
|
||||
}
|
||||
}
|
||||
|
||||
// Cached reference to the bone with the highest world-Y position at model-ready time.
|
||||
// 模型就绪时世界Y最高的骨骼缓存引用。
|
||||
private Transform _cachedTopBone;
|
||||
|
||||
/// <summary>
|
||||
/// Scan all SkinnedMeshRenderer bones, find the one with the highest world-Y, and cache it.
|
||||
/// Call once after the model and its first animation frame are ready (e.g. from UINPC coroutine).
|
||||
/// 扫描所有SkinnedMeshRenderer骨骼,找到世界Y最高者并缓存。
|
||||
/// 在模型及首帧动画就绪后调用一次(例如从UINPC协程中调用)。
|
||||
/// </summary>
|
||||
public void CacheTopBone()
|
||||
{
|
||||
var smrs = GetComponentsInChildren<SkinnedMeshRenderer>(true);
|
||||
var seen = new HashSet<Transform>();
|
||||
Transform highest = null;
|
||||
float highestY = float.MinValue;
|
||||
foreach (var smr in smrs)
|
||||
{
|
||||
if (smr == null || smr.bones == null)
|
||||
continue;
|
||||
foreach (var bone in smr.bones)
|
||||
{
|
||||
if (bone == null || !seen.Add(bone))
|
||||
continue;
|
||||
float y = bone.position.y;
|
||||
if (y > highestY)
|
||||
{
|
||||
highestY = y;
|
||||
highest = bone;
|
||||
}
|
||||
}
|
||||
}
|
||||
_cachedTopBone = highest;
|
||||
if (debugNamePlateBounds && _cachedTopBone != null)
|
||||
Debug.Log($"[Cuong] [NPCVisual] CacheTopBone: topBone={_cachedTopBone.name} worldY={highestY:F3}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the world position of the cached top bone (set by <see cref="CacheTopBone"/>).
|
||||
/// Returns false if no bone has been cached yet.
|
||||
/// 返回缓存的最高骨骼世界坐标。若尚未缓存则返回false。
|
||||
/// </summary>
|
||||
public bool TryGetTopBoneWorld(out Vector3 worldPos)
|
||||
{
|
||||
if (_cachedTopBone == null)
|
||||
{
|
||||
worldPos = default;
|
||||
return false;
|
||||
}
|
||||
worldPos = _cachedTopBone.position;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resolve world anchor from merged bounds of all SkinnedMeshRenderers.
|
||||
/// 从所有SkinnedMeshRenderer合并后的包围盒解析世界锚点。
|
||||
|
||||
@@ -314,6 +314,21 @@ namespace CSNetwork.C2SCommand
|
||||
public int id_task; // Task ID
|
||||
}
|
||||
|
||||
public struct cmd_assist_sel
|
||||
{
|
||||
public int idTeamMember;
|
||||
}
|
||||
|
||||
public struct cmd_bind_player_request
|
||||
{
|
||||
public int target;
|
||||
}
|
||||
|
||||
public struct cmd_bind_player_invite
|
||||
{
|
||||
public int target;
|
||||
}
|
||||
|
||||
public struct cmd_error_msg
|
||||
{
|
||||
public int iMessage;
|
||||
|
||||
@@ -1045,6 +1045,21 @@ namespace CSNetwork.C2SCommand
|
||||
return SerializeCommand(CommandID.ACTIVE_RUSH_FLY, pCmd);
|
||||
}
|
||||
|
||||
public static Octets CreateTeamAssistSelCommand(int idTeamMember)
|
||||
{
|
||||
return SerializeCommand(CommandID.ASSIST_SELECT, new cmd_assist_sel { idTeamMember = idTeamMember });
|
||||
}
|
||||
|
||||
public static Octets CreateBindPlayerRequestCommand(int idTarget)
|
||||
{
|
||||
return SerializeCommand(CommandID.BIND_PLAYER_REQUEST, new cmd_bind_player_request { target = idTarget });
|
||||
}
|
||||
|
||||
public static Octets CreateBindPlayerInviteCommand(int idTarget)
|
||||
{
|
||||
return SerializeCommand(CommandID.BIND_PLAYER_INVITE, new cmd_bind_player_invite { target = idTarget });
|
||||
}
|
||||
|
||||
public static Octets CreatePetCtrlCmd(int idTarget, int cmd, byte[] pParamBuf, int iParamLen)
|
||||
{
|
||||
cmd_pet_ctrl pCmd = new cmd_pet_ctrl();
|
||||
|
||||
@@ -2830,6 +2830,18 @@ namespace CSNetwork.GPDataType
|
||||
public int object_id;
|
||||
};
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct cmd_object_sit_down
|
||||
{
|
||||
public int id;
|
||||
};
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct cmd_object_stand_up
|
||||
{
|
||||
public int id;
|
||||
};
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct cmd_host_rush_fly
|
||||
{
|
||||
|
||||
@@ -1572,6 +1572,11 @@ namespace CSNetwork
|
||||
|
||||
break;
|
||||
}
|
||||
case CommandID.OBJECT_SIT_DOWN:
|
||||
case CommandID.OBJECT_STAND_UP:
|
||||
|
||||
EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PLAYERSITDOWN, MANAGER_INDEX.MAN_PLAYER, -1, pDataBuf, pCmdHeader);
|
||||
break;
|
||||
default:
|
||||
#if UNITY_EDITOR
|
||||
if (isDebug)
|
||||
@@ -2962,6 +2967,54 @@ namespace CSNetwork
|
||||
SendProtocol(gamedatasend);
|
||||
}
|
||||
|
||||
public void c2s_SendCmdSitDown()
|
||||
{
|
||||
var g = new gamedatasend();
|
||||
g.Data = C2SCommandFactory.CreateNakeCmd(C2SCommand.CommandID.SIT_DOWN);
|
||||
SendProtocol(g);
|
||||
}
|
||||
|
||||
public void c2s_SendCmdTeamAssistSel(int idTeamMember)
|
||||
{
|
||||
var g = new gamedatasend();
|
||||
g.Data = C2SCommandFactory.CreateTeamAssistSelCommand(idTeamMember);
|
||||
SendProtocol(g);
|
||||
}
|
||||
|
||||
public void c2s_SendCmdOpenBoothTest()
|
||||
{
|
||||
var g = new gamedatasend();
|
||||
g.Data = C2SCommandFactory.CreateNakeCmd(C2SCommand.CommandID.OPEN_BOOTH_TEST);
|
||||
SendProtocol(g);
|
||||
}
|
||||
|
||||
public void c2s_SendCmdBindPlayerRequest(int idTarget)
|
||||
{
|
||||
var g = new gamedatasend();
|
||||
g.Data = C2SCommandFactory.CreateBindPlayerRequestCommand(idTarget);
|
||||
SendProtocol(g);
|
||||
}
|
||||
|
||||
public void c2s_SendCmdBindPlayerInvite(int idTarget)
|
||||
{
|
||||
var g = new gamedatasend();
|
||||
g.Data = C2SCommandFactory.CreateBindPlayerInviteCommand(idTarget);
|
||||
SendProtocol(g);
|
||||
}
|
||||
|
||||
/// <summary>Port of CECGameSession::trade_Start.</summary>
|
||||
public bool trade_Start(int idTarget)
|
||||
{
|
||||
var p = new tradestart
|
||||
{
|
||||
Roleid = m_iCharID,
|
||||
Partner_roleid = idTarget,
|
||||
Localsid = (int)_localsid
|
||||
};
|
||||
SendProtocol(p);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void c2s_SendCmdPetCtrl(int idTarget, int cmd, byte[] pParamBuf, int iParamLen)
|
||||
{
|
||||
gamedatasend gamedatasend = new gamedatasend();
|
||||
|
||||
@@ -655,6 +655,42 @@ namespace BrewMonster.Network
|
||||
{
|
||||
Instance._gameSession.c2s_SendCmdStandUp();
|
||||
}
|
||||
|
||||
public static void c2s_CmdSitDown()
|
||||
{
|
||||
BMLogger.LogError("HoangDev: c2s_CmdSitDown");
|
||||
Instance._gameSession.c2s_SendCmdSitDown();
|
||||
}
|
||||
|
||||
public static void c2s_CmdTeamAssistSel(int idTeamMember)
|
||||
{
|
||||
Instance._gameSession.c2s_SendCmdTeamAssistSel(idTeamMember);
|
||||
}
|
||||
|
||||
public static void c2s_CmdActiveRushFly(bool bActive)
|
||||
{
|
||||
Instance._gameSession.c2s_SendCmdActiveRushFly(bActive);
|
||||
}
|
||||
|
||||
public static void c2s_CmdOpenBoothTest()
|
||||
{
|
||||
Instance._gameSession.c2s_SendCmdOpenBoothTest();
|
||||
}
|
||||
|
||||
public static void c2s_CmdBindPlayerRequest(int idTarget)
|
||||
{
|
||||
Instance._gameSession.c2s_SendCmdBindPlayerRequest(idTarget);
|
||||
}
|
||||
|
||||
public static void c2s_CmdBindPlayerInvite(int idTarget)
|
||||
{
|
||||
Instance._gameSession.c2s_SendCmdBindPlayerInvite(idTarget);
|
||||
}
|
||||
|
||||
public static bool trade_Start(int idTarget)
|
||||
{
|
||||
return Instance._gameSession.trade_Start(idTarget);
|
||||
}
|
||||
#region Task
|
||||
public static void c2s_CmdGetAllData(bool byPack, bool byEquip, bool byTask)
|
||||
{
|
||||
@@ -666,6 +702,11 @@ namespace BrewMonster.Network
|
||||
{
|
||||
Instance._gameSession.c2s_SendCmdEmoteAction(wPose);
|
||||
}
|
||||
|
||||
public static void c2s_CmdSessionEmote(int iPose)
|
||||
{
|
||||
Instance._gameSession.c2s_SendCmdEmoteAction((uint)iPose);
|
||||
}
|
||||
public static void c2s_CmdTaskNotify( byte[] pBuf, uint sz)
|
||||
{
|
||||
if (Instance != null && Instance._gameSession != null)
|
||||
|
||||
@@ -37,6 +37,10 @@ namespace PerfectWorld.Scripts
|
||||
public const uint MATTER_MONEY = 3;
|
||||
public const uint MATTER_TYPEMASK = 0xff;
|
||||
|
||||
private const float MatterNameExtraWorldYOffset = 0.05f;
|
||||
private const float MatterNameFallbackLocalY = 0.6f;
|
||||
private const string ItemNameTextChildName = "ItemNameText";
|
||||
|
||||
// Constructor / Constructor
|
||||
public CECMatter()
|
||||
{
|
||||
@@ -179,11 +183,24 @@ namespace PerfectWorld.Scripts
|
||||
var collider = matterObject.AddComponent<BoxCollider>();
|
||||
//this is a workaround to fix the collider size issue when load prefab go wrong at some point
|
||||
//TODO: remove this workaround after the prefab load issue is fixed
|
||||
Vector3 size = matterObject.GetComponentInChildren<Renderer>().bounds.size;
|
||||
if (size.x < 0.5f) size.x = 0.5f;
|
||||
if (size.y < 0.5f) size.y = 0.5f;
|
||||
if (size.z < 0.5f) size.z = 0.5f;
|
||||
collider.size = size;
|
||||
if (TryGetCombinedRendererBounds(matterObject.transform, null, out var combinedBounds))
|
||||
{
|
||||
Vector3 size = combinedBounds.size;
|
||||
if (size.x < 0.5f) size.x = 0.5f;
|
||||
if (size.y < 0.5f) size.y = 0.5f;
|
||||
if (size.z < 0.5f) size.z = 0.5f;
|
||||
collider.size = size;
|
||||
collider.center = matterObject.transform.InverseTransformPoint(combinedBounds.center);
|
||||
}
|
||||
else
|
||||
{
|
||||
var firstRenderer = matterObject.GetComponentInChildren<Renderer>();
|
||||
Vector3 size = firstRenderer != null ? firstRenderer.bounds.size : Vector3.one;
|
||||
if (size.x < 0.5f) size.x = 0.5f;
|
||||
if (size.y < 0.5f) size.y = 0.5f;
|
||||
if (size.z < 0.5f) size.z = 0.5f;
|
||||
collider.size = size;
|
||||
}
|
||||
}
|
||||
// Create text object to display item name above the cube
|
||||
CreateItemNameText(matterObject, Info.tid);
|
||||
@@ -244,18 +261,109 @@ namespace PerfectWorld.Scripts
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Merge world-space bounds of all child Renderers (MeshRenderer + SkinnedMeshRenderer).
|
||||
/// Reads sharedMesh.bounds (mesh local space) and manually converts to world space —
|
||||
/// same approach as PlayerVisual/NPCVisual — to avoid stale renderer.bounds after SetActive.
|
||||
/// 合并所有子 Renderer 的世界包围盒(MeshRenderer + SkinnedMeshRenderer)。
|
||||
/// 直接读 sharedMesh.bounds(网格本地空间)再手动转为世界坐标,避免 SetActive 后同帧 renderer.bounds 未刷新的问题。
|
||||
/// </summary>
|
||||
private static bool TryGetCombinedRendererBounds(Transform matterRoot, Transform excludeSubtree, out Bounds combinedBounds)
|
||||
{
|
||||
combinedBounds = default;
|
||||
if (matterRoot == null)
|
||||
return false;
|
||||
|
||||
var renderers = matterRoot.GetComponentsInChildren<Renderer>(true);
|
||||
bool hasAny = false;
|
||||
for (int i = 0; i < renderers.Length; i++)
|
||||
{
|
||||
var renderer = renderers[i];
|
||||
if (renderer == null)
|
||||
continue;
|
||||
if (excludeSubtree != null && renderer.transform.IsChildOf(excludeSubtree))
|
||||
continue;
|
||||
|
||||
Mesh mesh = null;
|
||||
if (renderer is SkinnedMeshRenderer smr)
|
||||
{
|
||||
mesh = smr.sharedMesh;
|
||||
}
|
||||
else if (renderer is MeshRenderer)
|
||||
{
|
||||
var mf = renderer.GetComponent<MeshFilter>();
|
||||
if (mf != null)
|
||||
mesh = mf.sharedMesh;
|
||||
}
|
||||
|
||||
if (mesh == null)
|
||||
continue;
|
||||
|
||||
// Manually build world-space bounds from mesh-local bounds + transform,
|
||||
// identical to PlayerVisual/NPCVisual — reliable even right after SetActive(true).
|
||||
// 与 PlayerVisual/NPCVisual 相同:从网格本地包围盒手动计算世界包围盒,SetActive 后同帧可靠。
|
||||
var meshBounds = mesh.bounds;
|
||||
var scale = renderer.transform.lossyScale;
|
||||
var worldCenter = renderer.transform.TransformPoint(meshBounds.center);
|
||||
var worldSize = new Vector3(
|
||||
Mathf.Abs(meshBounds.size.x * scale.x),
|
||||
Mathf.Abs(meshBounds.size.y * scale.y),
|
||||
Mathf.Abs(meshBounds.size.z * scale.z));
|
||||
var currentBounds = new Bounds(worldCenter, worldSize);
|
||||
|
||||
Debug.Log($"[Cuong] [CECMatter] renderer={renderer.name} meshLocalCenter={meshBounds.center} meshLocalSize={meshBounds.size} worldCenter={worldCenter} worldSize={worldSize} worldMaxY={currentBounds.max.y}");
|
||||
|
||||
if (!hasAny)
|
||||
{
|
||||
combinedBounds = currentBounds;
|
||||
hasAny = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
combinedBounds.Encapsulate(currentBounds);
|
||||
}
|
||||
}
|
||||
|
||||
return hasAny;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Name anchor at top of tallest mesh: combinedBounds.max.y in world, converted to local.
|
||||
/// 名牌锚点位于最高 mesh 顶部:世界坐标 combinedBounds.max.y,再转为本地坐标。
|
||||
/// </summary>
|
||||
private static bool TryGetItemNameAnchorLocal(Transform matterRoot, out Vector3 localAnchor)
|
||||
{
|
||||
if (!TryGetCombinedRendererBounds(matterRoot, null, out var combinedBounds))
|
||||
{
|
||||
localAnchor = new Vector3(0f, MatterNameFallbackLocalY, 0f);
|
||||
return false;
|
||||
}
|
||||
|
||||
var worldAnchor = new Vector3(
|
||||
combinedBounds.center.x,
|
||||
combinedBounds.max.y + MatterNameExtraWorldYOffset,
|
||||
combinedBounds.center.z);
|
||||
localAnchor = matterRoot.InverseTransformPoint(worldAnchor);
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void CreateItemNameText(GameObject matterObject, int tid)
|
||||
{
|
||||
if (matterObject == null)
|
||||
return;
|
||||
|
||||
// Avoid duplicating if prefab already contains it (or Init called twice).
|
||||
if (matterObject.transform.Find("ItemNameText") != null)
|
||||
if (matterObject.transform.Find(ItemNameTextChildName) != null)
|
||||
return;
|
||||
|
||||
var textObject = new GameObject("ItemNameText");
|
||||
var textObject = new GameObject(ItemNameTextChildName);
|
||||
textObject.transform.SetParent(matterObject.transform, false);
|
||||
textObject.transform.localPosition = new Vector3(0f, 0.6f, 0f);
|
||||
if (!TryGetItemNameAnchorLocal(matterObject.transform, out var localAnchor))
|
||||
{
|
||||
Debug.LogWarning(
|
||||
$"[Cuong] [CECMatter] No renderer bounds for '{matterObject.name}'; using fallback Y={MatterNameFallbackLocalY}");
|
||||
}
|
||||
textObject.transform.localPosition = localAnchor;
|
||||
|
||||
var textMesh = textObject.AddComponent<TextMeshPro>();
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ using BrewMonster.Assets.PerfectWorld.Scripts.Skills;
|
||||
using BrewMonster.Network;
|
||||
using BrewMonster.Scripts;
|
||||
using BrewMonster.Scripts.Skills;
|
||||
using static BrewMonster.Scripts.FixedMsg;
|
||||
using CSNetwork.C2SCommand;
|
||||
using CSNetwork.GPDataType;
|
||||
using CSNetwork.S2CCommand;
|
||||
@@ -513,7 +514,7 @@ namespace BrewMonster
|
||||
data.AddRange(BitConverter.GetBytes((int)cmdSC.GetParam()));
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case CECShortcut.ShortcutType.SCT_SKILL:
|
||||
{
|
||||
CECSCSkill skillSC = (CECSCSkill)pSC;
|
||||
@@ -949,61 +950,61 @@ namespace BrewMonster
|
||||
public override bool Execute()
|
||||
{
|
||||
CECHostPlayer pHost = CECGameRun.Instance.GetHostPlayer();
|
||||
if (!pHost || !pHost.IsAllResReady())
|
||||
if (pHost == null || !pHost.IsAllResReady())
|
||||
return false;
|
||||
|
||||
// if (GetCoolTime(0)>0)
|
||||
// {
|
||||
// bool bForbidCmd = true;
|
||||
// if (m_iCommand == CMD_RUSHFLY && pHost.GetRushFlyFlag())
|
||||
// bForbidCmd = false;
|
||||
//
|
||||
// if (bForbidCmd)
|
||||
// {
|
||||
// g_pGame.GetGameRun().AddFixedMessage(FIXMSG_CMD_INCOOLTIME);
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
switch (m_iCommand)
|
||||
int iMax = 0;
|
||||
if (GetCoolTime(ref iMax) > 0)
|
||||
{
|
||||
// case CMD_SITDOWN: pHost.CmdSitDown(!pHost.IsSitting()); break;
|
||||
// case CMD_WALKRUN: pHost.CmdWalkRun(!pHost.GetWalkRunFlag()); break;
|
||||
bool bForbidCmd = true;
|
||||
if ((CommandID)m_iCommand == CMD_RUSHFLY && pHost.GetRushFlyFlag())
|
||||
bForbidCmd = false;
|
||||
|
||||
if (bForbidCmd)
|
||||
{
|
||||
CECGameRun.Instance?.AddFixedMessage((int)FIXMSG_CMD_INCOOLTIME);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
BMLogger.LogError("HoangDev: (CommandID)m_iCommand:"+(CommandID)m_iCommand);
|
||||
switch ((CommandID)m_iCommand)
|
||||
{
|
||||
case CMD_SITDOWN: pHost.CmdSitDown(!pHost.IsSitting()); break;
|
||||
case CMD_WALKRUN: pHost.CmdWalkRun(!pHost.GetWalkRunFlag()); break;
|
||||
// case CMD_NORMALATTACK: pHost.CmdNormalAttack(); break;
|
||||
// case CMD_FINDTARGET: pHost.CmdFindTarget(); break;
|
||||
// case CMD_ASSISTATTACK: pHost.CmdAssistAttack(); break;
|
||||
// case CMD_INVITETOTEAM: pHost.CmdInviteToTeam(); break;
|
||||
// case CMD_LEAVETEAM: pHost.CmdLeaveTeam(); break;
|
||||
// case CMD_KICKTEAMMEM: pHost.CmdKickTeamMember(); break;
|
||||
// case CMD_FINDTEAM: pHost.CmdFindTeam(); break;
|
||||
// case CMD_STARTTRADE: pHost.CmdStartTrade(); break;
|
||||
// case CMD_SELLBOOTH: pHost.CmdSellBooth(); break;
|
||||
// case CMD_BUYBOOTH: pHost.CmdBuyBooth(); break;
|
||||
case (int)CommandID.CMD_PLAYPOSE: pHost.CmdStartPose((int)m_dwParam); break;
|
||||
// case CMD_INVITETOFACTION: pHost.CmdInviteToFaction(); break;
|
||||
case (int)CommandID.CMD_FLY:
|
||||
case CMD_FINDTARGET: pHost.CmdFindTarget(); break;
|
||||
case CMD_ASSISTATTACK: pHost.CmdAssistAttack(); break;
|
||||
case CMD_INVITETOTEAM: pHost.CmdInviteToTeam(); break;
|
||||
case CMD_LEAVETEAM: pHost.CmdLeaveTeam(); break;
|
||||
case CMD_KICKTEAMMEM: pHost.CmdKickTeamMember(); break;
|
||||
case CMD_FINDTEAM: pHost.CmdFindTeam(); break;
|
||||
case CMD_STARTTRADE: pHost.CmdStartTrade(); break;
|
||||
case CMD_SELLBOOTH: pHost.CmdSellBooth(); break;
|
||||
case CMD_BUYBOOTH: pHost.CmdBuyBooth(); break;
|
||||
case CMD_PLAYPOSE: pHost.CmdStartPose((int)m_dwParam); break;
|
||||
case CMD_INVITETOFACTION: pHost.CmdInviteToFaction(); break;
|
||||
case CMD_FLY:
|
||||
{
|
||||
// 如果骑乘要飞行,则这些 action switcher,否则 CmdFly
|
||||
// If riding wants to fly, then these action switcher, otherwise CmdFly
|
||||
// Call CmdFly(true) to match F4 key behavior
|
||||
// Manual fly toggle should also cancel any active auto-route/AutoPF move.
|
||||
// Use same behavior as local input (F4) so the player regains control immediately.
|
||||
var wm = pHost.GetWorkMan();
|
||||
if (wm != null)
|
||||
// If riding wants to fly, use action switcher; otherwise CmdFly
|
||||
if (pHost.GetActionSwitcher()?.OnRideToFlyAction() != true)
|
||||
{
|
||||
var mw = wm.GetRunningWork(CECHPWork.Host_work_ID.WORK_MOVETOPOS) as CECHPWorkMove;
|
||||
if (mw != null && mw.GetAutoMove())
|
||||
var wm = pHost.GetWorkMan();
|
||||
if (wm != null)
|
||||
{
|
||||
wm.FinishRunningWork(CECHPWork.Host_work_ID.WORK_MOVETOPOS);
|
||||
var mw = wm.GetRunningWork(CECHPWork.Host_work_ID.WORK_MOVETOPOS) as CECHPWorkMove;
|
||||
if (mw != null && mw.GetAutoMove())
|
||||
wm.FinishRunningWork(CECHPWork.Host_work_ID.WORK_MOVETOPOS);
|
||||
}
|
||||
CECIntelligentRoute.Instance().ResetSearch();
|
||||
pHost.CmdFly(true);
|
||||
}
|
||||
CECIntelligentRoute.Instance().ResetSearch();
|
||||
pHost.CmdFly(true);
|
||||
break;
|
||||
}
|
||||
// case CMD_PICKUP: pHost.CmdPickup(); break;
|
||||
// case CMD_GATHER: pHost.CmdGather(); break;
|
||||
// case CMD_RUSHFLY: pHost.CmdRushFly(); break;
|
||||
// case CMD_BINDBUDDY: pHost.CmdBindBuddy(pHost.GetSelectedTarget()); break;
|
||||
case CMD_GATHER: pHost.CmdGather(); break;
|
||||
case CMD_RUSHFLY: pHost.CmdRushFly(); break;
|
||||
case CMD_BINDBUDDY: pHost.CmdBindBuddy(pHost.GetSelectedTarget()); break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@@ -1079,37 +1080,34 @@ namespace BrewMonster
|
||||
|
||||
return szIconFile;
|
||||
}
|
||||
// Get item cool time
|
||||
int GetCoolTime(ref int piMax/* NULL */)
|
||||
public override int GetCoolTime(ref int piMax)
|
||||
{
|
||||
CECHostPlayer pHost = CECGameRun.Instance.GetHostPlayer();
|
||||
int iTime = 0;
|
||||
piMax = 0;
|
||||
|
||||
if (pHost == null)
|
||||
return 0;
|
||||
|
||||
switch ((CommandID)m_iCommand)
|
||||
{
|
||||
case CommandID.CMD_RUSHFLY:
|
||||
|
||||
// iTime = pHost.GetCoolTime(GP_CT_FLY_RUSH, piMax);
|
||||
case CMD_RUSHFLY:
|
||||
iTime = pHost.GetCoolTime((int)CoolTimeIndex.GP_CT_FLY_RUSH, out piMax);
|
||||
break;
|
||||
|
||||
case CommandID.CMD_PLAYPOSE:
|
||||
// todo need to get cooldown here
|
||||
// iTime = pHost.GetCoolTime(GP_CT_EMOTE, piMax);
|
||||
case CMD_PLAYPOSE:
|
||||
iTime = pHost.GetCoolTime((int)CoolTimeIndex.GP_CT_EMOTE, out piMax);
|
||||
break;
|
||||
|
||||
case CommandID.CMD_BINDBUDDY:
|
||||
case CMD_BINDBUDDY:
|
||||
{
|
||||
// CECCounter& cnt = pHost.GetBindCmdCoolCnt();
|
||||
// iTime = cnt.GetPeriod() - cnt.GetCounter();
|
||||
//
|
||||
// if (piMax)
|
||||
// *piMax = cnt.GetPeriod();
|
||||
|
||||
CECCounter cnt = pHost.GetBindCmdCoolCnt();
|
||||
iTime = (int)(cnt.GetPeriod() - cnt.GetCounter());
|
||||
piMax = (int)cnt.GetPeriod();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
||||
// if (piMax) *piMax = 0;
|
||||
piMax = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -206,6 +206,9 @@ namespace BrewMonster.Assets.PerfectWorld.Scripts.Players
|
||||
public void SetPostMessageFlag(bool bCan) { m_bCanAddMsg = bCan; }
|
||||
|
||||
public virtual bool OnFlyToRideAction(int petIndex) { return false; } // fly -> ride
|
||||
|
||||
/// <summary>Ride mount then fly (shortcut CMD_FLY). 骑乘后飞行</summary>
|
||||
public virtual bool OnRideToFlyAction() { return false; }
|
||||
}
|
||||
public enum EMsgActionSwitcher
|
||||
|
||||
|
||||
@@ -497,6 +497,7 @@ namespace BrewMonster
|
||||
switch (Msg.dwMsg)
|
||||
{
|
||||
case EC_MsgDef.MSG_PM_PLAYERFLY: OnMsgPlayerFly(Msg); break;
|
||||
case EC_MsgDef.MSG_PM_PLAYERSITDOWN: OnMsgPlayerSitDown(Msg); break;
|
||||
case EC_MsgDef.MSG_PM_PLAYERBASEINFO: OnMsgPlayerBaseInfo(Msg); break;
|
||||
case EC_MsgDef.MSG_PM_PLAYEREXTSTATE: OnMsgPlayerExtState(Msg); break;
|
||||
case EC_MsgDef.MSG_PM_PLAYEREQUIPDATA: OnMsgPlayerEquipData(Msg); break;
|
||||
@@ -1202,6 +1203,22 @@ namespace BrewMonster
|
||||
m_dwStates |= (uint)PlayerNPCState.GP_STATE_FLY;
|
||||
}
|
||||
|
||||
void OnMsgPlayerSitDown(ECMSG Msg)
|
||||
{
|
||||
if (Convert.ToInt32(Msg.dwParam2) == CommandID.OBJECT_SIT_DOWN)
|
||||
{
|
||||
m_dwStates |= (uint)PlayerNPCState.GP_STATE_SITDOWN;
|
||||
m_pEPWorkMan.StartNormalWork(new CECEPWorkIdle(m_pEPWorkMan, CECEPWork.Idle_work_type.IDLE_SITDOWN, 0, 0));
|
||||
}
|
||||
else // OBJECT_STAND_UP
|
||||
{
|
||||
m_dwStates &= ~(uint)PlayerNPCState.GP_STATE_SITDOWN;
|
||||
if (m_pEPWorkMan.IsWorkRunning(CECEPWork.EP_work_ID.WORK_IDLE))
|
||||
PlayAction((int)PLAYER_ACTION_TYPE.ACT_STANDUP);
|
||||
m_pEPWorkMan.FinishIdleWork(CECEPWork.Idle_work_type.IDLE_SITDOWN);
|
||||
}
|
||||
}
|
||||
|
||||
// Load player equipments
|
||||
bool LoadPlayerEquipments()
|
||||
{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using BrewMonster.Network;
|
||||
using BrewMonster.Network;
|
||||
using BrewMonster.Scripts;
|
||||
using BrewMonster.Scripts.Pet;
|
||||
using CSNetwork.GPDataType;
|
||||
@@ -461,15 +461,15 @@ namespace BrewMonster.UI
|
||||
{
|
||||
if(m_textPetName != null)
|
||||
{
|
||||
m_textPetName.text = "___";
|
||||
m_textPetName.text = "";
|
||||
}
|
||||
if(m_textLevel != null)
|
||||
{
|
||||
m_textLevel.text = "___";
|
||||
m_textLevel.text = "";
|
||||
}
|
||||
if(m_textExp != null)
|
||||
{
|
||||
m_textExp.text = "___";
|
||||
m_textExp.text = "";
|
||||
}
|
||||
if (m_iconPet != null && m_spriteDefault_Icon != null)
|
||||
{
|
||||
@@ -477,7 +477,7 @@ namespace BrewMonster.UI
|
||||
}
|
||||
if(m_descPet != null)
|
||||
{
|
||||
m_descPet.text = "___";
|
||||
m_descPet.text = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,9 @@ namespace BrewMonster
|
||||
[SerializeField] private bool applyMaleHeadWorldOffsetForAabbOnly = true;
|
||||
[SerializeField] private float maleHeadWorldOffset = 0.1f;
|
||||
|
||||
[Header("NPC — skeleton hook")]
|
||||
[SerializeField] private bool useNpcHeadHook = true;
|
||||
|
||||
[Header("NPC — SMR / root fallback")]
|
||||
[SerializeField] private bool preferVisualBoundsFallback = true;
|
||||
[SerializeField] private float fallbackHeightAboveRoot = 2f;
|
||||
@@ -55,6 +58,17 @@ namespace BrewMonster
|
||||
npcVisual = hostNpc.GetComponent<NPCVisual>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Trigger a scan of all NPC skeleton bones to cache the highest-Y bone.
|
||||
/// Call from <see cref="UINPC"/> once the NPC model and its animation are ready.
|
||||
/// 触发扫描NPC所有骨骼以缓存世界Y最高的骨骼。在NPC模型及动画就绪后由UINPC调用一次。
|
||||
/// </summary>
|
||||
public void RefreshNpcTopBone()
|
||||
{
|
||||
CacheRefs();
|
||||
npcVisual?.CacheTopBone();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resolve world position for the nameplate canvas root. Call once at init or every frame if the plate should follow the host.
|
||||
/// 解析名牌Canvas根的世界坐标。仅在初始化时调用一次,或若名牌需跟随宿主则每帧调用。
|
||||
@@ -119,6 +133,29 @@ namespace BrewMonster
|
||||
if (hostNpc == null)
|
||||
return false;
|
||||
|
||||
// Priority 1: skeleton hook (follows animation every frame — fixes floating/flying NPCs like 小星星).
|
||||
// 优先级1:骨骼挂点(每帧跟随动画,修复小星星等浮空动画中名牌与模型重叠的问题)。
|
||||
if (useNpcHeadHook)
|
||||
{
|
||||
var headHook = hostNpc.GetHook(headHookName);
|
||||
if (headHook != null)
|
||||
{
|
||||
worldPos = headHook.position + Vector3.up * (headHookWorldOffset + extraWorldYOffset);
|
||||
usedSkinnedMeshMergedBounds = true; // treated as "precise anchor" so UINPC coroutine exits early
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Priority 2: cached top bone — bone with highest world-Y found at model-ready time.
|
||||
// Follows animation per-frame via UINPC.LateUpdate without needing a specific bone name.
|
||||
// 优先级2:缓存的最高骨骼——模型就绪时世界Y最高的骨骼,每帧跟随动画,无需特定骨骼名。
|
||||
if (npcVisual != null && npcVisual.TryGetTopBoneWorld(out worldPos))
|
||||
{
|
||||
usedSkinnedMeshMergedBounds = true;
|
||||
worldPos.y += extraWorldYOffset;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (preferVisualBoundsFallback
|
||||
&& npcVisual != null
|
||||
&& npcVisual.TryGetNamePlateAnchorWorld(out worldPos))
|
||||
|
||||
@@ -260,8 +260,6 @@ namespace BrewMonster
|
||||
enumSkillLearnedState learnedState = model.GetSkillLearnedState(m_skillID);
|
||||
|
||||
int requiredItem = model.GetRequiredBook(m_skillID, m_curLevel + 1);
|
||||
if(m_skillID == 1)
|
||||
BMLogger.LogError($"UpdateUpgradeBtn learnedState:{learnedState}, fitLevel={fitLevel}, requiredItem:{requiredItem}, model.CheckPreItem(requiredItem):{model.CheckPreItem(requiredItem)}");
|
||||
if (enumSkillLearnedState.SKILL_FULL != learnedState &&
|
||||
enumSkillFitLevelState.SKILL_FIT_LEVEL == fitLevel &&
|
||||
(requiredItem == 0 || model.CheckPreItem(requiredItem)))
|
||||
|
||||
@@ -63,6 +63,22 @@ namespace BrewMonster
|
||||
_initialNameplateRoutine = StartCoroutine(CoApplyInitialNameplateDeferred(maxFrames: 120));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update nameplate position every frame so it follows skeleton animations (e.g. floating/flying NPCs or monsters).
|
||||
/// Only active after the initial anchor coroutine has resolved (i.e. _initialNameplateRoutine == null).
|
||||
/// 每帧更新名牌位置,使其跟随骨骼动画(如浮空/飞行的NPC或怪物,例如小星星)。
|
||||
/// 仅在初始锚点协程完成后(_initialNameplateRoutine == null)生效。
|
||||
/// </summary>
|
||||
private void LateUpdate()
|
||||
{
|
||||
if (_initialNameplateRoutine != null)
|
||||
return;
|
||||
if (_canvasRoot == null || _nameplateAnchor == null)
|
||||
return;
|
||||
if (_nameplateAnchor.TryGetWorldPosition(out var worldPos))
|
||||
ApplyCanvasRootLocalPosition(worldPos);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Call after NPC model async load (e.g. <see cref="CECNPC.QueueLoadNPCModel"/>) so SMR bounds exist before anchoring.
|
||||
/// 在NPC模型异步加载完成后调用(如 <see cref="CECNPC.QueueLoadNPCModel"/>),以便SMR包围盒已存在再定位名牌。
|
||||
@@ -107,12 +123,17 @@ namespace BrewMonster
|
||||
&& fromSmr)
|
||||
{
|
||||
ApplyCanvasRootLocalPosition(worldPos);
|
||||
// Model + SMR ready: scan bones and cache the highest one for per-frame LateUpdate tracking.
|
||||
// 模型和SMR就绪:扫描骨骼并缓存最高骨骼,供LateUpdate每帧跟踪。
|
||||
_nameplateAnchor.RefreshNpcTopBone();
|
||||
_initialNameplateRoutine = null;
|
||||
yield break;
|
||||
}
|
||||
yield return null;
|
||||
}
|
||||
|
||||
// Timeout: set position from whatever is available (hook / SMR / root fallback), then still cache top bone.
|
||||
// 超时:使用当前可用方式设置位置(挂点/SMR/根节点回退),仍然缓存最高骨骼。
|
||||
if (_nameplateAnchor.TryGetWorldPosition(out var finalPos, out _, logNpcRootFallback: true))
|
||||
{
|
||||
ApplyCanvasRootLocalPosition(finalPos);
|
||||
@@ -125,6 +146,7 @@ namespace BrewMonster
|
||||
"NPC with SMR bounds: worldPos = (combinedBounds.center.x, combinedBounds.max.y, combinedBounds.center.z) + Vector3.up * extraWorldYOffset. " +
|
||||
"NPC fallback: worldPos = hostNpc.transform.position + Vector3.up * (fallbackHeightAboveRoot + extraWorldYOffset).");
|
||||
}
|
||||
_nameplateAnchor.RefreshNpcTopBone();
|
||||
_initialNameplateRoutine = null;
|
||||
}
|
||||
|
||||
|
||||
@@ -32,9 +32,25 @@ namespace BrewMonster.Scripts.World
|
||||
return m_pOnmtMan;
|
||||
}
|
||||
public float GetTerrainHeight(A3DVECTOR3 vPos, ref A3DVECTOR3 pvNormal /* NULL */)
|
||||
{
|
||||
A3DVECTOR3 normal = pvNormal;
|
||||
if (!TryGetTerrainHeight(vPos, ref normal, out float height))
|
||||
return vPos.y;
|
||||
pvNormal = normal;
|
||||
return height;
|
||||
}
|
||||
|
||||
/// <summary>False when terrain is not loaded yet (e.g. during early AutoPF Search).</summary>
|
||||
public bool TryGetTerrainHeight(A3DVECTOR3 vPos, ref A3DVECTOR3 pvNormal, out float height)
|
||||
{
|
||||
A3DTerrain2 pTerrain = GetTerrain();
|
||||
return pTerrain.GetPosHeight(vPos, ref pvNormal);
|
||||
if (pTerrain == null)
|
||||
{
|
||||
height = vPos.y;
|
||||
return false;
|
||||
}
|
||||
height = pTerrain.GetPosHeight(vPos, ref pvNormal);
|
||||
return true;
|
||||
}
|
||||
|
||||
public float GetWaterHeight(A3DVECTOR3 vPos)
|
||||
|
||||
@@ -353,7 +353,7 @@ MonoBehaviour:
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_text: ___
|
||||
m_text:
|
||||
m_isRightToLeft: 0
|
||||
m_fontAsset: {fileID: 11400000, guid: 369c2e14814cc9a4b8e3ad4e37769134, type: 2}
|
||||
m_sharedMaterial: {fileID: 9092487103257209053, guid: 369c2e14814cc9a4b8e3ad4e37769134, type: 2}
|
||||
@@ -380,7 +380,7 @@ MonoBehaviour:
|
||||
m_faceColor:
|
||||
serializedVersion: 2
|
||||
rgba: 4294967295
|
||||
m_fontSize: 39.15
|
||||
m_fontSize: 36
|
||||
m_fontSizeBase: 36
|
||||
m_fontWeight: 400
|
||||
m_enableAutoSizing: 1
|
||||
@@ -565,7 +565,7 @@ MonoBehaviour:
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_text: ___
|
||||
m_text:
|
||||
m_isRightToLeft: 0
|
||||
m_fontAsset: {fileID: 11400000, guid: 369c2e14814cc9a4b8e3ad4e37769134, type: 2}
|
||||
m_sharedMaterial: {fileID: 9092487103257209053, guid: 369c2e14814cc9a4b8e3ad4e37769134, type: 2}
|
||||
@@ -592,7 +592,7 @@ MonoBehaviour:
|
||||
m_faceColor:
|
||||
serializedVersion: 2
|
||||
rgba: 4294967295
|
||||
m_fontSize: 39.15
|
||||
m_fontSize: 36
|
||||
m_fontSizeBase: 36
|
||||
m_fontWeight: 400
|
||||
m_enableAutoSizing: 1
|
||||
@@ -1464,6 +1464,7 @@ MonoBehaviour:
|
||||
m_EditorClassIdentifier:
|
||||
skillNameText: {fileID: 0}
|
||||
imageProgress: {fileID: 0}
|
||||
btnCancel: {fileID: 0}
|
||||
m_prefabPetSlot: {fileID: 4659787501825667672, guid: 1f24da0ec1a703b4e9650d69ec4ceff2, type: 3}
|
||||
m_container: {fileID: 6146182060371184350}
|
||||
m_btnClose: {fileID: 8122086289517642079}
|
||||
@@ -1655,6 +1656,7 @@ MonoBehaviour:
|
||||
m_EditorClassIdentifier:
|
||||
skillNameText: {fileID: 0}
|
||||
imageProgress: {fileID: 0}
|
||||
btnCancel: {fileID: 0}
|
||||
m_iconPet: {fileID: 3806612095625030478}
|
||||
m_textPetName: {fileID: 3493020700139178670}
|
||||
m_textLevel: {fileID: 7602645980480065390}
|
||||
@@ -1933,7 +1935,7 @@ MonoBehaviour:
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_text: New Text
|
||||
m_text:
|
||||
m_isRightToLeft: 0
|
||||
m_fontAsset: {fileID: 11400000, guid: 369c2e14814cc9a4b8e3ad4e37769134, type: 2}
|
||||
m_sharedMaterial: {fileID: 9092487103257209053, guid: 369c2e14814cc9a4b8e3ad4e37769134, type: 2}
|
||||
@@ -2373,7 +2375,7 @@ MonoBehaviour:
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_text: ___
|
||||
m_text:
|
||||
m_isRightToLeft: 0
|
||||
m_fontAsset: {fileID: 11400000, guid: 369c2e14814cc9a4b8e3ad4e37769134, type: 2}
|
||||
m_sharedMaterial: {fileID: 9092487103257209053, guid: 369c2e14814cc9a4b8e3ad4e37769134, type: 2}
|
||||
@@ -2400,7 +2402,7 @@ MonoBehaviour:
|
||||
m_faceColor:
|
||||
serializedVersion: 2
|
||||
rgba: 4294967295
|
||||
m_fontSize: 39.15
|
||||
m_fontSize: 36
|
||||
m_fontSizeBase: 36
|
||||
m_fontWeight: 400
|
||||
m_enableAutoSizing: 1
|
||||
|
||||
@@ -11419,9 +11419,9 @@ MonoBehaviour:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastTarget: 0
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
m_Maskable: 0
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
@@ -17603,7 +17603,7 @@ GameObject:
|
||||
- component: {fileID: 9178171791072353269}
|
||||
- component: {fileID: 7628333317866785984}
|
||||
m_Layer: 5
|
||||
m_Name: GameObject
|
||||
m_Name: View
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
@@ -17650,7 +17650,7 @@ MonoBehaviour:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastTarget: 0
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
{
|
||||
"items": [
|
||||
{
|
||||
"header": 1992,
|
||||
"param": 0,
|
||||
"hasParam": false,
|
||||
"describe": "Buff rage",
|
||||
"lastUsedUtcTicks": 639138321717437357
|
||||
},
|
||||
{
|
||||
"header": 8903,
|
||||
"param": 73125,
|
||||
"hasParam": true,
|
||||
"describe": "NoCooldown",
|
||||
"lastUsedUtcTicks": 639138321659072960
|
||||
"lastUsedUtcTicks": 639147565037094641
|
||||
},
|
||||
{
|
||||
"header": 1992,
|
||||
"param": 0,
|
||||
"hasParam": false,
|
||||
"describe": "Buff rage",
|
||||
"lastUsedUtcTicks": 639147564992569650
|
||||
},
|
||||
{
|
||||
"header": 2000,
|
||||
|
||||
@@ -0,0 +1,259 @@
|
||||
using BrewMonster.Managers;
|
||||
using BrewMonster.Network;
|
||||
using BrewMonster.Scripts;
|
||||
using BrewMonster.UI;
|
||||
using CSNetwork.GPDataType;
|
||||
using PerfectWorld.Scripts.Managers;
|
||||
using UnityEngine;
|
||||
using static BrewMonster.Scripts.CECHPWork;
|
||||
using static BrewMonster.CECHPWorkTrace;
|
||||
|
||||
namespace BrewMonster
|
||||
{
|
||||
public partial class CECHostPlayer
|
||||
{
|
||||
public bool GetWalkRunFlag() => m_bWalkRun;
|
||||
public bool GetRushFlyFlag() => m_bRushFly;
|
||||
|
||||
CECCounter m_BindCmdCoolCnt = new CECCounter();
|
||||
|
||||
public CECCounter GetBindCmdCoolCnt() => m_BindCmdCoolCnt;
|
||||
|
||||
void InitBindCmdCoolCnt()
|
||||
{
|
||||
m_BindCmdCoolCnt.SetPeriod(35000);
|
||||
m_BindCmdCoolCnt.Reset(true);
|
||||
}
|
||||
|
||||
// Sit down / Stand up
|
||||
// 坐下 / 站起
|
||||
public bool CmdSitDown(bool bSitDown)
|
||||
{
|
||||
BMLogger.LogError("HoangDev: CmdSitDown:"+bSitDown);
|
||||
if (!CanDo(ActionCanDo.CANDO_SITDOWN))
|
||||
return false;
|
||||
|
||||
if (bSitDown)
|
||||
UnityGameSession.c2s_CmdSitDown();
|
||||
else
|
||||
UnityGameSession.c2s_CmdStandUp();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Switch walk and run state
|
||||
// 切换走/跑状态
|
||||
public bool CmdWalkRun(bool bRun)
|
||||
{
|
||||
m_bWalkRun = bRun;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Find a near target (stub)
|
||||
// 寻找附近目标(占位)
|
||||
public bool CmdFindTarget()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Select other player's attacked target
|
||||
// 选择队友正在攻击的目标
|
||||
public bool CmdAssistAttack()
|
||||
{
|
||||
if (m_pWorkMan.IsSitting())
|
||||
{
|
||||
UnityGameSession.c2s_CmdStandUp();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (CanDo(ActionCanDo.CANDO_ASSISTSEL))
|
||||
UnityGameSession.c2s_CmdTeamAssistSel(m_idSelTarget);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Invite selected player to join team
|
||||
// 邀请选中的玩家入队
|
||||
public bool CmdInviteToTeam()
|
||||
{
|
||||
if (IsDead() || !GPDataTypeHelper.ISPLAYERID(m_idSelTarget) || m_idSelTarget == GetCharacterID())
|
||||
return false;
|
||||
|
||||
UnityGameSession.c2s_CmdTeamInvite(m_idSelTarget);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Leave current team (confirmation dialog)
|
||||
// 离开当前队伍(确认框)
|
||||
public bool CmdLeaveTeam()
|
||||
{
|
||||
if (IsDead() || m_pTeam == null)
|
||||
return false;
|
||||
|
||||
string szMsg = CECUIManager.Instance?.GetInGameUIMan()?.GetStringFromTable(235)
|
||||
?? "Are you sure you want to leave the team?";
|
||||
CECUIManager.Instance?.ShowMessageBoxYesAndNo("", szMsg, null,
|
||||
() => UnityGameSession.c2s_CmdTeamLeaveParty(), null);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Kick one member of team (stub)
|
||||
// 踢出队员(占位)
|
||||
public bool CmdKickTeamMember()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Search for a team (stub)
|
||||
// 寻找队伍(占位)
|
||||
public bool CmdFindTeam()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Start trade with other selected player
|
||||
// 与选中玩家开始交易
|
||||
public bool CmdStartTrade()
|
||||
{
|
||||
if (m_pWorkMan.IsSitting())
|
||||
{
|
||||
UnityGameSession.c2s_CmdStandUp();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CanDo(ActionCanDo.CANDO_TRADE))
|
||||
return false;
|
||||
|
||||
if (!GPDataTypeHelper.ISPLAYERID(m_idSelTarget) || m_idSelTarget == m_PlayerInfo.cid)
|
||||
return false;
|
||||
|
||||
UnityGameSession.trade_Start(m_idSelTarget);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Open booth for selling items
|
||||
// 开摊出售
|
||||
public bool CmdSellBooth()
|
||||
{
|
||||
if (IsInvisible())
|
||||
{
|
||||
CECGameRun.Instance?.AddFixedMessage((int)FixedMsg.FIXMSG_CANNOT_USE_WHEN_INVISIBLE);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_pWorkMan.IsSitting())
|
||||
{
|
||||
UnityGameSession.c2s_CmdStandUp();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_pWorkMan.IsFollowing())
|
||||
m_pWorkMan.FinishAllWork(true);
|
||||
|
||||
if (!CanDo(ActionCanDo.CANDO_BOOTH))
|
||||
return false;
|
||||
|
||||
UnityGameSession.c2s_CmdOpenBoothTest();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Open booth for buying items (stub)
|
||||
// 开摊收购(占位)
|
||||
public bool CmdBuyBooth()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Invite selected player to join faction (stub)
|
||||
// 邀请入帮(占位)
|
||||
public bool CmdInviteToFaction()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/*public bool CmdPickup()
|
||||
{
|
||||
if (m_pWorkMan.IsSitting())
|
||||
{
|
||||
UnityGameSession.c2s_CmdStandUp();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CanDo(ActionCanDo.CANDO_PICKUP))
|
||||
return false;
|
||||
|
||||
CECHPWork pWork = m_pWorkMan.GetWork(Host_work_ID.WORK_TRACEOBJECT);
|
||||
if (pWork is CECHPWorkTrace pTrace &&
|
||||
pTrace.GetTraceReason() == Trace_reason.TRACE_PICKUP)
|
||||
return true;
|
||||
|
||||
EC_ManMatter matterMan = EC_ManMessageMono.Instance?.EC_ManMatter;
|
||||
CECMatter pMatter = matterMan?.FindMatterNearHost(10.0f, true);
|
||||
if (pMatter != null)
|
||||
PickupObject(pMatter.GetMatterID(), false);
|
||||
|
||||
return true;
|
||||
}*/
|
||||
|
||||
public bool CmdGather()
|
||||
{
|
||||
if (m_pWorkMan.IsSitting())
|
||||
{
|
||||
UnityGameSession.c2s_CmdStandUp();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CanDo(ActionCanDo.CANDO_GATHER))
|
||||
return false;
|
||||
|
||||
CECHPWork pWork = m_pWorkMan.GetWork(Host_work_ID.WORK_TRACEOBJECT);
|
||||
if (pWork is CECHPWorkTrace pTrace &&
|
||||
pTrace.GetTraceReason() == Trace_reason.TRACE_GATHER)
|
||||
return true;
|
||||
|
||||
PickupObject(m_idSelTarget, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool CmdRushFly()
|
||||
{
|
||||
if (m_bAboutToDie || IsDead() || !IsFlying())
|
||||
return false;
|
||||
|
||||
UnityGameSession.c2s_CmdActiveRushFly(!m_bRushFly);
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool CmdBindBuddy(int idTarget)
|
||||
{
|
||||
if (!m_BindCmdCoolCnt.IsFull())
|
||||
{
|
||||
CECGameRun.Instance?.AddFixedMessage((int)FixedMsg.FIXMSG_CMD_INCOOLTIME);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CanDo(ActionCanDo.CANDO_BINDBUDDY) || !GPDataTypeHelper.ISPLAYERID(idTarget) ||
|
||||
idTarget == GetCharacterID())
|
||||
return false;
|
||||
|
||||
EC_ElsePlayer pPlayer = m_pPlayerMan?.GetElsePlayer(idTarget);
|
||||
if (pPlayer == null || pPlayer.GetGender() == GetGender())
|
||||
return false;
|
||||
|
||||
A3DVECTOR3 vDist = pPlayer.GetServerPos() - GetPos();
|
||||
if (vDist.Magnitude() >= 2.8f)
|
||||
{
|
||||
CECGameRun.Instance?.AddFixedMessage((int)FixedMsg.FIXMSG_TARGETISFAR);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (GetGender() == GENDER.GENDER_MALE)
|
||||
UnityGameSession.c2s_CmdBindPlayerInvite(idTarget);
|
||||
else
|
||||
UnityGameSession.c2s_CmdBindPlayerRequest(idTarget);
|
||||
|
||||
m_BindCmdCoolCnt.Reset();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 61bcfdcbd8ffcd746b0e59990cc6970b
|
||||
@@ -135,6 +135,7 @@ namespace BrewMonster
|
||||
int iAction = (int)PLAYER_ACTION_TYPE.ACT_STAND;
|
||||
bool bSession = false;
|
||||
|
||||
BMLogger.LogError("HoangDev: idEmote "+idEmote);
|
||||
// Select action according to pose
|
||||
switch (idEmote)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
using System;
|
||||
using BrewMonster.Network;
|
||||
using BrewMonster.Scripts;
|
||||
using BrewMonster.Scripts.Task;
|
||||
using CSNetwork;
|
||||
using CSNetwork.GPDataType;
|
||||
|
||||
namespace BrewMonster
|
||||
{
|
||||
public partial class CECHostPlayer
|
||||
{
|
||||
private void OnMsgPlayerSitDown(ECMSG Msg)
|
||||
{
|
||||
if (Convert.ToInt32(Msg.dwParam2) == CommandID.OBJECT_SIT_DOWN)
|
||||
{
|
||||
if (m_pWorkMan.IsMovingToPosition() ||
|
||||
m_pWorkMan.IsTracing() ||
|
||||
m_pWorkMan.IsFollowing())
|
||||
{
|
||||
m_MoveCtrl.SendStopMoveCmd(EC_Utility.ToVector3(GetPos()), GetGroundSpeed(), (int)GPMoveMode.GP_MOVE_RUN);
|
||||
}
|
||||
|
||||
m_dwStates |= (uint)PlayerNPCState.GP_STATE_SITDOWN;
|
||||
CECHPWorkSit pWork = (CECHPWorkSit)m_pWorkMan.CreateWork(CECHPWork.Host_work_ID.WORK_SIT);
|
||||
pWork.SetBeSittingFlag(false);
|
||||
m_pWorkMan.StartWork_p1(pWork);
|
||||
|
||||
GetTaskInterface().SetEmotion((int)TaskInterface.CommandTaskAction.CMD_EMOTION_SITDOWN);
|
||||
}
|
||||
else if (Convert.ToInt32(Msg.dwParam2) == CommandID.OBJECT_STAND_UP)
|
||||
{
|
||||
m_dwStates &= ~(uint)PlayerNPCState.GP_STATE_SITDOWN;
|
||||
CECHPWorkStand pWork = (CECHPWorkStand)m_pWorkMan.CreateWork(CECHPWork.Host_work_ID.WORK_STAND);
|
||||
m_pWorkMan.StartWork_p1(pWork);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3b8afadf7e5c78f409d4e8746ef6ea77
|
||||
@@ -565,6 +565,7 @@ namespace BrewMonster
|
||||
case EC_MsgDef.MSG_HST_COOLTIMEDATA: OnMsgHstCoolTimeData(Msg); break;
|
||||
case EC_MsgDef.MSG_HST_PRESSCANCEL: OnMsgHstPressCancel(Msg); break;
|
||||
case EC_MsgDef.MSG_PM_PLAYERFLY: OnMsgPlayerFly(Msg); break;
|
||||
case EC_MsgDef.MSG_PM_PLAYERSITDOWN: OnMsgPlayerSitDown(Msg); break;
|
||||
case EC_MsgDef.MSG_HST_PETOPT: OnMsgHstPetOpt(Msg); break;
|
||||
case EC_MsgDef.MSG_HST_SETPLAYERLIMIT: OnMsgHstSetPlayerLimit(Msg); break;
|
||||
case EC_MsgDef.MSG_PM_PLAYERMOUNT: OnMsgPlayerMount(Msg); break;
|
||||
@@ -1327,6 +1328,7 @@ namespace BrewMonster
|
||||
m_IncantCnt = new CECCounter();
|
||||
m_IncantCnt.SetPeriod(1000);
|
||||
m_IncantCnt.Reset(true);
|
||||
InitBindCmdCoolCnt();
|
||||
m_bEnterGame = false;
|
||||
}
|
||||
|
||||
@@ -3374,7 +3376,8 @@ namespace BrewMonster
|
||||
|
||||
if (iPose == (int)RoleExpression.ROLEEXP_SITDOWN)
|
||||
{
|
||||
// UnityGameSession.c2s_CmdSessionEmote(iPose);
|
||||
BMLogger.LogError("HoangDev: c2s_CmdSessionEmote: "+iPose);
|
||||
UnityGameSession.c2s_CmdSessionEmote(iPose);
|
||||
}
|
||||
else if (iPose == (int)RoleExpression.ROLEEXP_KISS)
|
||||
{
|
||||
@@ -3655,9 +3658,10 @@ namespace BrewMonster
|
||||
|
||||
m_PetOptCnt.IncCounter(iRealTime);
|
||||
// Bind command cool counter
|
||||
/* if (m_BindCmdCoolCnt.IncCounter(dwDeltaTime))
|
||||
m_BindCmdCoolCnt.Reset(true);
|
||||
if (m_BindCmdCoolCnt.IncCounter(iRealTime))
|
||||
m_BindCmdCoolCnt.Reset(true);
|
||||
|
||||
/*
|
||||
// Auto fashion time counter
|
||||
if (m_bAutoFashion && GetBoothState() != 2 && !IsShapeChanged())
|
||||
{
|
||||
|
||||
@@ -222,6 +222,7 @@ namespace BrewMonster
|
||||
{
|
||||
return;
|
||||
}
|
||||
BMLogger.LogError("HoangDev animationName:"+animationName);
|
||||
bool isState = namedAnimancer.States.TryGet(animationName, out var existingState) ? true : false;
|
||||
if (isState)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user