Merge pull request 'aniamtion processs' (#11) from feature/movement into develop
Reviewed-on: https://git.brew.monster/Unity/perfect-world-unity/pulls/11
This commit is contained in:
Binary file not shown.
@@ -94,7 +94,7 @@ namespace BrewMonster
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogError($"AutoInitializer: Failed to initialize {type.FullName}: {ex}");
|
||||
Debug.LogError($"AutoInitializer: Failed to initialize {type.FullName}: {ex} {ex.StackTrace}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +36,8 @@ namespace PerfectWorld.Scripts.Managers
|
||||
var edm = ElementDataManProvider.GetElementDataMan();
|
||||
if (edm == null) return CacheAndReturn(templateId, "");
|
||||
uint id = unchecked((uint)templateId);
|
||||
object data = edm.get_data_ptr(id, ID_SPACE.ID_SPACE_ESSENCE);
|
||||
DATA_TYPE dATA_TYPE = default;
|
||||
object data = edm.get_data_ptr(id, ID_SPACE.ID_SPACE_ESSENCE,ref dATA_TYPE);
|
||||
string name = ExtractNameFromElement(data);
|
||||
if (string.IsNullOrEmpty(name))
|
||||
{
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0ee9b2b0487546348a46b02d6183bfd2
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,132 @@
|
||||
#_begin
|
||||
|
||||
// 0
|
||||
站立
|
||||
战斗站立
|
||||
行走
|
||||
奔跑
|
||||
起跳
|
||||
|
||||
// 5
|
||||
起跳空中循环
|
||||
跳跃落地
|
||||
游动
|
||||
漂浮
|
||||
翅膀起飞
|
||||
|
||||
// 10
|
||||
翅膀悬停
|
||||
翅膀前进
|
||||
翅膀高空下降
|
||||
翅膀低空下降
|
||||
翅膀落地
|
||||
|
||||
// 15
|
||||
飞剑起飞
|
||||
飞剑悬停
|
||||
飞剑前进
|
||||
飞剑高空下降
|
||||
飞剑低空下降
|
||||
|
||||
// 20
|
||||
飞剑落地
|
||||
打坐
|
||||
打坐循环
|
||||
打坐站起
|
||||
受伤
|
||||
|
||||
// 25
|
||||
陆地死亡
|
||||
死亡地面循环
|
||||
水中死亡
|
||||
死亡水中循环
|
||||
空中死亡
|
||||
|
||||
// 30
|
||||
空中死亡下落循环
|
||||
空中死亡落地
|
||||
死亡落地循环
|
||||
复活
|
||||
长休闲动作头
|
||||
|
||||
// 35
|
||||
被击退
|
||||
被击倒
|
||||
被击倒倒地循环
|
||||
被击倒站起
|
||||
采摘
|
||||
|
||||
// 40
|
||||
采摘植物循环
|
||||
采摘站起
|
||||
捡东西
|
||||
伸懒腰
|
||||
四处张望
|
||||
|
||||
// 45
|
||||
转动兵器
|
||||
招手
|
||||
点头
|
||||
摇头
|
||||
耸肩膀
|
||||
|
||||
// 50
|
||||
大笑
|
||||
生气
|
||||
晕倒
|
||||
沮丧
|
||||
飞吻
|
||||
|
||||
// 55
|
||||
害羞
|
||||
抱拳
|
||||
坐下
|
||||
坐下循环
|
||||
坐下站起
|
||||
|
||||
// 60
|
||||
冲锋
|
||||
思考
|
||||
挑衅
|
||||
胜利
|
||||
亲吻
|
||||
|
||||
// 65
|
||||
亲吻循环
|
||||
亲吻结束
|
||||
普攻1
|
||||
普攻2
|
||||
普攻3
|
||||
|
||||
// 70
|
||||
普攻4
|
||||
放暗器
|
||||
花招跑
|
||||
花招跳
|
||||
翅膀滑翔
|
||||
|
||||
// 75
|
||||
飞剑滑翔
|
||||
战斗
|
||||
攻击1
|
||||
攻击2
|
||||
攻击3
|
||||
|
||||
// 80
|
||||
攻击4
|
||||
防御
|
||||
摔倒
|
||||
倒地
|
||||
张望
|
||||
|
||||
// 85
|
||||
舞蹈
|
||||
时装武器
|
||||
使用物品
|
||||
使用物品循环
|
||||
双人亲吻
|
||||
|
||||
// 90
|
||||
使用道具
|
||||
移动攻击漂浮
|
||||
新烟花
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 51f9ac299dd9beb40bde3afc767036bf
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -17,7 +17,7 @@ using static UnityEngine.InputManagerEntry;
|
||||
using Unity.VisualScripting;
|
||||
using PerfectWorld.Scripts.Managers;
|
||||
|
||||
public class CECHostPlayer : MonoBehaviour
|
||||
public class CECHostPlayer : EC_Player
|
||||
{
|
||||
[SerializeField] private TextMeshPro txtName;
|
||||
[SerializeField] private CharacterController controller;
|
||||
@@ -59,6 +59,7 @@ public class CECHostPlayer : MonoBehaviour
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
base.Awake();
|
||||
_moveState = new PlayerMoveState(this);
|
||||
_idleState = new PlayerIdleState(this);
|
||||
_playerStateMachine = new PlayerStateMachine();
|
||||
|
||||
@@ -0,0 +1,190 @@
|
||||
using ModelRenderer.Scripts.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using UnityEngine; // thêm để dùng Resources & TextAsset
|
||||
|
||||
public class CECStringTab
|
||||
{
|
||||
private readonly Dictionary<int, string> m_AStrTab = new Dictionary<int, string>();
|
||||
private readonly Dictionary<int, string> m_WStrTab = new Dictionary<int, string>();
|
||||
|
||||
private bool m_bInit = false;
|
||||
private bool m_bUnicode = false;
|
||||
|
||||
public CECStringTab() { }
|
||||
~CECStringTab() { Release(); }
|
||||
|
||||
public bool Init(string szFile, bool bUnicode)
|
||||
{
|
||||
Release();
|
||||
m_bUnicode = bUnicode;
|
||||
|
||||
try
|
||||
{
|
||||
bool ok = bUnicode ? LoadWideStrings(szFile) : LoadANSIStrings(szFile);
|
||||
m_bInit = ok;
|
||||
foreach(var str in m_AStrTab.Values)
|
||||
{
|
||||
BrewMonster.Logger.Log("HoangDev: m_AStrTab.Values" + str);
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogError($"[CECStringTab] Init failed: {e}");
|
||||
Release();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void Release()
|
||||
{
|
||||
m_AStrTab.Clear();
|
||||
m_WStrTab.Clear();
|
||||
m_bInit = false;
|
||||
m_bUnicode = false;
|
||||
}
|
||||
|
||||
public string GetANSIString(int n) => m_AStrTab.TryGetValue(n, out var s) ? s : null;
|
||||
public string GetWideString(int n) => m_WStrTab.TryGetValue(n, out var s) ? s : null;
|
||||
public string GetWideStringObject(int n) => GetWideString(n);
|
||||
public bool IsInitialized() => m_bInit;
|
||||
|
||||
// ==== Đọc từ Resources thay vì đường dẫn ====
|
||||
|
||||
protected bool LoadANSIStrings(string resourceName)
|
||||
{
|
||||
TextAsset textAsset = Resources.Load<TextAsset>(resourceName);
|
||||
if (textAsset == null)
|
||||
{
|
||||
Debug.LogError($"[CECStringTab] Resource not found: {resourceName}");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Giải mã bytes -> string (ANSI: dùng Encoding.Default)
|
||||
string content = ByteToStringUtils.ByteArrayToCP936String(textAsset.bytes);
|
||||
using var sr = new StringReader(content);
|
||||
return ParseIntoDict(sr, isWide: false);
|
||||
}
|
||||
|
||||
protected bool LoadWideStrings(string resourceName)
|
||||
{
|
||||
TextAsset textAsset = Resources.Load<TextAsset>(resourceName);
|
||||
if (textAsset == null)
|
||||
{
|
||||
Debug.LogError($"[CECStringTab] Resource not found: {resourceName}");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Unity TextAsset mặc định đã decode text UTF8 -> textAsset.text
|
||||
// nhưng để chắc chắn BOM/Unicode thì đọc từ bytes
|
||||
string content;
|
||||
content = ByteToStringUtils.ByteArrayToUnicodeString(textAsset.bytes);
|
||||
|
||||
using var sr = new StringReader(content);
|
||||
return ParseIntoDict(sr, isWide: true);
|
||||
}
|
||||
|
||||
private static Encoding DetectEncoding(byte[] bom)
|
||||
{
|
||||
if (bom.Length >= 3 && bom[0] == 0xEF && bom[1] == 0xBB && bom[2] == 0xBF) return Encoding.UTF8;
|
||||
if (bom.Length >= 2 && bom[0] == 0xFF && bom[1] == 0xFE) return Encoding.Unicode;
|
||||
if (bom.Length >= 2 && bom[0] == 0xFE && bom[1] == 0xFF) return Encoding.BigEndianUnicode;
|
||||
return null;
|
||||
}
|
||||
|
||||
private bool ParseIntoDict(StringReader sr, bool isWide)
|
||||
{
|
||||
bool bIndexMode = false;
|
||||
bool bBegan = false;
|
||||
int autoIndex = 0;
|
||||
|
||||
var allLines = new List<string>();
|
||||
string line;
|
||||
while ((line = sr.ReadLine()) != null)
|
||||
{
|
||||
allLines.Add(line);
|
||||
}
|
||||
|
||||
for (int i = 0; i < allLines.Count; i++)
|
||||
{
|
||||
var ln = allLines[i].Trim();
|
||||
if (ln.Length == 0) continue;
|
||||
|
||||
if (ln.Equals("#_index", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
bIndexMode = true;
|
||||
}
|
||||
else if (ln.Equals("#_begin", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
bBegan = true;
|
||||
|
||||
for (int j = i + 1; j < allLines.Count; j++)
|
||||
{
|
||||
var payload = allLines[j].Trim();
|
||||
if (payload.Length == 0) continue;
|
||||
if (payload.StartsWith("#")) continue;
|
||||
|
||||
if (bIndexMode)
|
||||
{
|
||||
if (!TrySplitIndexAndText(payload, out int idx, out string text))
|
||||
continue;
|
||||
PutString(idx, text, isWide);
|
||||
}
|
||||
else
|
||||
{
|
||||
PutString(autoIndex++, payload, isWide);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return bBegan;
|
||||
}
|
||||
|
||||
private static bool TrySplitIndexAndText(string line, out int index, out string text)
|
||||
{
|
||||
index = 0; text = null;
|
||||
|
||||
int eq = line.IndexOf('=');
|
||||
if (eq >= 0)
|
||||
{
|
||||
var left = line.Substring(0, eq).Trim();
|
||||
var right = line.Substring(eq + 1);
|
||||
if (int.TryParse(left, out index))
|
||||
{
|
||||
text = right;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int sp = FirstWhiteSpaceIndex(line);
|
||||
if (sp <= 0) return false;
|
||||
|
||||
var left2 = line.Substring(0, sp).Trim();
|
||||
var right2 = line.Substring(sp).TrimStart();
|
||||
if (int.TryParse(left2, out index))
|
||||
{
|
||||
text = right2;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static int FirstWhiteSpaceIndex(string s)
|
||||
{
|
||||
for (int i = 0; i < s.Length; i++)
|
||||
if (char.IsWhiteSpace(s[i])) return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
private void PutString(int id, string value, bool isWide)
|
||||
{
|
||||
if (isWide) m_WStrTab[id] = value;
|
||||
else m_AStrTab[id] = value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: db8df7318b3376c4fb57c2cce332cf85
|
||||
@@ -1,5 +1,8 @@
|
||||
using System;
|
||||
using BrewMonster;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
using static EC_Player;
|
||||
|
||||
public static class EC_Utility
|
||||
{
|
||||
@@ -30,8 +33,22 @@ public static class EC_Utility
|
||||
{
|
||||
return new System.Numerics.Vector3(v.x, v.y, v.z);
|
||||
}
|
||||
public static float MagnitudeH(this Vector3 v)
|
||||
public static float MagnitudeH(this Vector3 v)
|
||||
{
|
||||
return Mathf.Sqrt(v.x * v.x + v.z * v.z);
|
||||
}
|
||||
public static string BuildActionName(PLAYER_ACTION action, int weaponType)
|
||||
{
|
||||
string prefix = action.data.ActionPrefix ?? string.Empty;
|
||||
string suffix = string.Empty;
|
||||
|
||||
if (action.data.action_weapon_suffix != null
|
||||
&& weaponType >= 0
|
||||
&& weaponType < action.data.action_weapon_suffix.Length)
|
||||
{
|
||||
suffix = action.data.action_weapon_suffix[weaponType].Suffix ?? string.Empty;
|
||||
}
|
||||
|
||||
return $"{prefix}_{suffix}";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,261 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Timers;
|
||||
using UnityEngine;
|
||||
|
||||
public static class EventBus
|
||||
{
|
||||
private static readonly Dictionary<Type, Delegate> globalListeners = new();
|
||||
private static readonly Dictionary<Type, Delegate> globalClassListeners = new();
|
||||
|
||||
private static readonly Dictionary<int, Dictionary<Type, Delegate>> channelListeners = new();
|
||||
private static readonly Dictionary<int, Dictionary<Type, Delegate>> channelClassListeners = new();
|
||||
|
||||
private static Timer cleanupTimer;
|
||||
|
||||
public static bool DebugEnabled = false;
|
||||
|
||||
private static void DebugLog(string message)
|
||||
{
|
||||
if (DebugEnabled)
|
||||
Console.WriteLine($"[EventBus] {message}");
|
||||
}
|
||||
|
||||
// ===== GLOBAL STRUCT EVENTS =====
|
||||
public static void Subscribe<T>(Action<T> listener) where T : struct
|
||||
{
|
||||
var type = typeof(T);
|
||||
|
||||
if (!globalListeners.ContainsKey(typeof(T)))
|
||||
globalListeners[type] = null;
|
||||
|
||||
globalListeners[type] = (Action<T>)globalListeners[type] + listener;
|
||||
}
|
||||
|
||||
public static void Unsubscribe<T>(Action<T> listener) where T : struct
|
||||
{
|
||||
var type = typeof(T);
|
||||
if (globalListeners.ContainsKey(typeof(T)))
|
||||
{
|
||||
globalListeners[type] = (Action<T>)globalListeners[type] - listener;
|
||||
if (globalListeners[type] == null)
|
||||
globalListeners.Remove(type);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Publish<T>(T eventData) where T : struct
|
||||
{
|
||||
var type = typeof(T);
|
||||
if (globalListeners.TryGetValue(type, out var del) && del is Action<T> action)
|
||||
{
|
||||
DebugLog($"Publish Global Struct Event: {typeof(T).Name}");
|
||||
action.Invoke(eventData);
|
||||
}
|
||||
}
|
||||
|
||||
// ===== GLOBAL CLASS EVENTS =====
|
||||
public static void SubscribeClass<T>(Action<T> listener) where T : class
|
||||
{
|
||||
var type = typeof(T);
|
||||
if (!globalClassListeners.ContainsKey(type))
|
||||
globalClassListeners[type] = null;
|
||||
|
||||
globalClassListeners[type] = (Action<T>)globalClassListeners[type] + listener;
|
||||
}
|
||||
|
||||
public static void UnsubscribeClass<T>(Action<T> listener) where T : class
|
||||
{
|
||||
var type = typeof(T);
|
||||
if (globalClassListeners.ContainsKey(type))
|
||||
{
|
||||
globalClassListeners[type] = (Action<T>)globalClassListeners[type] - listener;
|
||||
if (globalClassListeners[type] == null)
|
||||
globalClassListeners.Remove(type);
|
||||
}
|
||||
}
|
||||
|
||||
public static void PublishClass<T>(T eventData) where T : class
|
||||
{
|
||||
var type = typeof(T);
|
||||
if (globalClassListeners.TryGetValue(type, out var del) && del is Action<T> action)
|
||||
{
|
||||
DebugLog($"Publish Global Class Event: {typeof(T).Name}");
|
||||
action.Invoke(eventData);
|
||||
}
|
||||
}
|
||||
|
||||
// ===== CHANNEL STRUCT EVENTS =====
|
||||
public static void SubscribeChannel<T>(int channelId, Action<T> listener) where T : struct
|
||||
{
|
||||
var type = typeof(T);
|
||||
|
||||
if (!channelListeners.ContainsKey(channelId))
|
||||
channelListeners[channelId] = new Dictionary<Type, Delegate>();
|
||||
|
||||
if (!channelListeners[channelId].ContainsKey(type))
|
||||
channelListeners[channelId][type] = null;
|
||||
|
||||
channelListeners[channelId][type] = (Action<T>)channelListeners[channelId][type] + listener;
|
||||
}
|
||||
|
||||
public static void UnsubscribeChannel<T>(int channelId, Action<T> listener) where T : struct
|
||||
{
|
||||
var type = typeof(T);
|
||||
if (channelListeners.ContainsKey(channelId) && channelListeners[channelId].ContainsKey(type))
|
||||
{
|
||||
channelListeners[channelId][type] = (Action<T>)channelListeners[channelId][type] - listener;
|
||||
if (channelListeners[channelId][type] == null)
|
||||
channelListeners[channelId].Remove(type);
|
||||
if (channelListeners[channelId].Count == 0)
|
||||
channelListeners.Remove(channelId);
|
||||
}
|
||||
}
|
||||
|
||||
public static void PublishChannel<T>(int channelId, T eventData) where T : struct
|
||||
{
|
||||
var type = typeof(T);
|
||||
if (channelListeners.TryGetValue(channelId, out var listeners) &&
|
||||
listeners.TryGetValue(type, out var del) &&
|
||||
del is Action<T> action)
|
||||
{
|
||||
DebugLog($"Publish Channel Struct Event: {type.Name} to channel '{channelId}'");
|
||||
action.Invoke(eventData);
|
||||
}
|
||||
}
|
||||
|
||||
// ===== CHANNEL CLASS EVENTS =====
|
||||
public static void SubscribeChannelClass<T>(int channelId, Action<T> listener) where T : class
|
||||
{
|
||||
var type = typeof(T);
|
||||
if (!channelClassListeners.ContainsKey(channelId))
|
||||
channelClassListeners[channelId] = new Dictionary<Type, Delegate>();
|
||||
|
||||
if (!channelClassListeners[channelId].ContainsKey(type))
|
||||
channelClassListeners[channelId][type] = null;
|
||||
|
||||
channelClassListeners[channelId][type] = (Action<T>)channelClassListeners[channelId][type] + listener;
|
||||
}
|
||||
|
||||
public static void UnsubscribeChannelClass<T>(int channelId, Action<T> listener) where T : class
|
||||
{
|
||||
var type = typeof(T);
|
||||
if (channelClassListeners.ContainsKey(channelId) && channelClassListeners[channelId].ContainsKey(type))
|
||||
{
|
||||
channelClassListeners[channelId][type] = (Action<T>)channelClassListeners[channelId][type] - listener;
|
||||
if (channelClassListeners[channelId][type] == null)
|
||||
channelClassListeners[channelId].Remove(type);
|
||||
if (channelClassListeners[channelId].Count == 0)
|
||||
channelClassListeners.Remove(channelId);
|
||||
}
|
||||
}
|
||||
|
||||
public static void PublishChannelClass<T>(int channelId, T eventData) where T : class
|
||||
{
|
||||
var type = typeof(T);
|
||||
if (channelClassListeners.TryGetValue(channelId, out var listeners) &&
|
||||
listeners.TryGetValue(type, out var del) &&
|
||||
del is Action<T> action)
|
||||
{
|
||||
DebugLog($"Publish Channel Class Event: {type.Name} to channel '{channelId}'");
|
||||
action.Invoke(eventData);
|
||||
}
|
||||
}
|
||||
|
||||
// ===== ONE-TIME SUBSCRIBE =====
|
||||
public static void SubscribeOnce<T>(Action<T> listener) where T : struct
|
||||
{
|
||||
Action<T> wrapper = null;
|
||||
wrapper = (data) =>
|
||||
{
|
||||
listener(data);
|
||||
Unsubscribe(wrapper);
|
||||
};
|
||||
Subscribe(wrapper);
|
||||
}
|
||||
|
||||
public static void SubscribeOnceClass<T>(Action<T> listener) where T : class
|
||||
{
|
||||
Action<T> wrapper = null;
|
||||
wrapper = (data) =>
|
||||
{
|
||||
listener(data);
|
||||
UnsubscribeClass(wrapper);
|
||||
};
|
||||
SubscribeClass(wrapper);
|
||||
}
|
||||
|
||||
public static void SubscribeOnceChannel<T>(int channelId, Action<T> listener) where T : struct
|
||||
{
|
||||
Action<T> wrapper = null;
|
||||
wrapper = (data) =>
|
||||
{
|
||||
listener(data);
|
||||
UnsubscribeChannel(channelId, wrapper);
|
||||
};
|
||||
SubscribeChannel(channelId, wrapper);
|
||||
}
|
||||
|
||||
public static void SubscribeOnceChannelClass<T>(int channelId, Action<T> listener) where T : class
|
||||
{
|
||||
Action<T> wrapper = null;
|
||||
wrapper = (data) =>
|
||||
{
|
||||
listener(data);
|
||||
UnsubscribeChannelClass(channelId, wrapper);
|
||||
};
|
||||
SubscribeChannelClass(channelId, wrapper);
|
||||
}
|
||||
|
||||
// ===== CHANNEL UTILITIES =====
|
||||
public static bool ChannelExists(int channelId)
|
||||
{
|
||||
return channelListeners.ContainsKey(channelId) || channelClassListeners.ContainsKey(channelId);
|
||||
}
|
||||
|
||||
public static void EnableAutoCleanup(float delaySeconds = 5f)
|
||||
{
|
||||
cleanupTimer = new Timer(delaySeconds * 1000);
|
||||
cleanupTimer.Elapsed += (sender, e) =>
|
||||
{
|
||||
var emptyStructChannels = channelListeners
|
||||
.Where(pair => pair.Value.Values.All(d => d == null))
|
||||
.Select(pair => pair.Key)
|
||||
.ToList();
|
||||
|
||||
foreach (var id in emptyStructChannels)
|
||||
{
|
||||
channelListeners.Remove(id);
|
||||
DebugLog($"Removed empty struct channel: {id}");
|
||||
}
|
||||
|
||||
var emptyClassChannels = channelClassListeners
|
||||
.Where(pair => pair.Value.Values.All(d => d == null))
|
||||
.Select(pair => pair.Key)
|
||||
.ToList();
|
||||
|
||||
foreach (var id in emptyClassChannels)
|
||||
{
|
||||
channelClassListeners.Remove(id);
|
||||
DebugLog($"Removed empty class channel: {id}");
|
||||
}
|
||||
};
|
||||
cleanupTimer.AutoReset = true;
|
||||
cleanupTimer.Start();
|
||||
}
|
||||
#if UNITY_EDITOR
|
||||
public static void LogAllActiveListeners()
|
||||
{
|
||||
foreach (var kv in globalListeners)
|
||||
{
|
||||
var methods = kv.Value?.GetInvocationList();
|
||||
if (methods != null && methods.Length > 0)
|
||||
{
|
||||
Debug.LogWarning($"[EventBus Leak] {kv.Key.Name} still has {methods.Length} listeners:");
|
||||
foreach (var m in methods)
|
||||
Debug.LogWarning($" - Target: {m.Target}, Method: {m.Method}");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f24ba7881ac213b4e905d525121d0a95
|
||||
@@ -57,6 +57,7 @@ public class GameController : MonoBehaviour
|
||||
Debug.LogError("null prefab");
|
||||
return;
|
||||
}
|
||||
EC_Player.InitStaticRes();
|
||||
hostPlayer = Instantiate(characterPrefab, transform);
|
||||
hostPlayer.InitCharacter(info);
|
||||
//Vector3 pos = new Vector3(info.pos.x, info.pos.y, info.pos.z);
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
using BrewMonster;
|
||||
using UnityEngine;
|
||||
|
||||
public class InitializePlayer /*: IAutoInitialize*/
|
||||
{
|
||||
public void Dispose()
|
||||
{
|
||||
EC_Player.Dispose();
|
||||
}
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
EC_Player.InitStaticRes();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d693d80f20d058a4786bf8234eeb0ce3
|
||||
@@ -1,6 +1,267 @@
|
||||
using BrewMonster;
|
||||
using ModelRenderer.Scripts.GameData;
|
||||
using Mono.Cecil;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class EC_Player
|
||||
public class EC_Player : MonoBehaviour
|
||||
{
|
||||
public Bounds m_aabbServer;
|
||||
private static PLAYER_ACTION[] _default_actions;
|
||||
private static PLAYER_ACTION[] _turning_actions;
|
||||
PLAYER_ACTION[] m_PlayerActions;
|
||||
|
||||
protected void Awake()
|
||||
{
|
||||
m_PlayerActions = _default_actions;
|
||||
BrewMonster.Logger.Log("m_PlayerActions " + m_PlayerActions.Length);
|
||||
}
|
||||
|
||||
public static void InitStaticRes()
|
||||
{
|
||||
BuildActionList();
|
||||
}
|
||||
private static void BuildActionList()
|
||||
{
|
||||
if (_default_actions == null)
|
||||
{
|
||||
// thay cho hashtab trong C++
|
||||
Dictionary<string, PLAYER_ACTION_INFO_CONFIG> actionMap =
|
||||
new Dictionary<string, PLAYER_ACTION_INFO_CONFIG>(100);
|
||||
|
||||
Dictionary<string, PLAYER_ACTION_INFO_CONFIG> skillActionMap =
|
||||
new Dictionary<string, PLAYER_ACTION_INFO_CONFIG>(100);
|
||||
|
||||
elementdataman dataman = ElementDataManProvider.GetElementDataMan();
|
||||
PLAYER_ACTION_INFO_CONFIG data;
|
||||
|
||||
int count = dataman.get_data_num(ID_SPACE.ID_SPACE_CONFIG);
|
||||
|
||||
DATA_TYPE dt = default;
|
||||
uint id = 0;
|
||||
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
id = dataman.get_data_id(ID_SPACE.ID_SPACE_CONFIG, i, ref dt);
|
||||
if (dt != DATA_TYPE.DT_PLAYER_ACTION_INFO_CONFIG)
|
||||
continue;
|
||||
|
||||
data = (PLAYER_ACTION_INFO_CONFIG)dataman.get_data_ptr(id, ID_SPACE.ID_SPACE_CONFIG, ref dt);
|
||||
if (!string.IsNullOrEmpty(data.ActionName) && data.ActionName[0] != '0')
|
||||
{
|
||||
if (!actionMap.TryAdd(data.ActionName, data))
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CECStringTab actionNames = new CECStringTab();
|
||||
actionNames.Init("actions_player", false);
|
||||
|
||||
_default_actions = new PLAYER_ACTION[(int)PLAYER_ACTION_TYPE.ACT_MAX];
|
||||
|
||||
for (int i = 0; i < _default_actions.Length; i++)
|
||||
{
|
||||
_default_actions[i].type = (PLAYER_ACTION_TYPE)i;
|
||||
|
||||
string szName = actionNames.GetANSIString(i);
|
||||
BrewMonster.Logger.Log("HoangDev: szName " + szName);
|
||||
|
||||
if (!string.IsNullOrEmpty(szName))
|
||||
{
|
||||
if (actionMap.TryGetValue(szName, out var it))
|
||||
{
|
||||
|
||||
_default_actions[i].data = it;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
public bool PlayAction(int iAction, bool bRestart/* true */, int iTransTime/* 200 */, bool bQueue/* false */)
|
||||
{
|
||||
return PlayActionWithConfig(iAction, 0, bRestart, iTransTime, bQueue);
|
||||
}
|
||||
public bool PlayActionWithConfig(int iAction, int actionConfigID, bool bRestart/* =true */, int iTransTime/* =200 */, bool bQueue/* =false */)
|
||||
{
|
||||
if (iAction < 0 || iAction >= (int)PLAYER_ACTION_TYPE.ACT_MAX)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (actionConfigID > 0)
|
||||
{
|
||||
DATA_TYPE dt = DATA_TYPE.DT_INVALID;
|
||||
var p = ElementDataManProvider.GetElementDataMan().get_data_ptr((uint)actionConfigID, ID_SPACE. ID_SPACE_CONFIG, ref dt);
|
||||
if (dt == DATA_TYPE.DT_PLAYER_ACTION_INFO_CONFIG)
|
||||
{
|
||||
PLAYER_ACTION actionConfig;
|
||||
actionConfig.type = (PLAYER_ACTION_TYPE)iAction;
|
||||
actionConfig.data = (PLAYER_ACTION_INFO_CONFIG) p;
|
||||
return PlayActionWithConfig(iAction, actionConfig, bRestart, iTransTime, bQueue);
|
||||
}
|
||||
else
|
||||
{
|
||||
BrewMonster.Logger.LogError($"CECPlayer::PlayActionWithConfig, invalid action config ID({actionConfigID})");
|
||||
}
|
||||
}
|
||||
return PlayActionWithConfig(iAction, m_PlayerActions[iAction], bRestart, iTransTime, bQueue);
|
||||
}
|
||||
public bool PlayActionWithConfig(int iAction, in PLAYER_ACTION actionConfig,
|
||||
bool bRestart = true, int iTransTime = 200, bool bQueue = false)
|
||||
{
|
||||
PLAYER_ACTION action = actionConfig;
|
||||
|
||||
var szAct = EC_Utility.BuildActionName(action, 10);
|
||||
|
||||
BrewMonster.Logger.Log("HoangDev : szActszAct " + szAct);
|
||||
return true;
|
||||
}
|
||||
public static void Dispose()
|
||||
{
|
||||
_default_actions = null;
|
||||
_turning_actions = null;
|
||||
}
|
||||
|
||||
|
||||
public struct PLAYER_ACTION
|
||||
{
|
||||
public PLAYER_ACTION_TYPE type;
|
||||
public PLAYER_ACTION_INFO_CONFIG data;
|
||||
};
|
||||
public enum PLAYER_ACTION_TYPE
|
||||
{
|
||||
// 0
|
||||
ACT_STAND = 0, // Đứng
|
||||
ACT_FIGHTSTAND, // Đứng chiến đấu
|
||||
ACT_WALK, // Đi bộ
|
||||
ACT_RUN, // Chạy
|
||||
ACT_JUMP_START, // Bắt đầu nhảy
|
||||
|
||||
// 5
|
||||
ACT_JUMP_LOOP, // Nhảy trên không lặp lại
|
||||
ACT_JUMP_LAND, // Nhảy tiếp đất
|
||||
ACT_SWIM, // Bơi
|
||||
ACT_HANGINWATER, // Lơ lửng trong nước
|
||||
ACT_TAKEOFF, // Cất cánh (should be ACT_TAKEOFF_WING)
|
||||
|
||||
// 10
|
||||
ACT_HANGINAIR, // Treo trên không (should be ACT_HANGINAIR_WING)
|
||||
ACT_FLY, // Bay (should be ACT_FLY_WING)
|
||||
ACT_FLYDOWN, // Bay xuống cao (should be ACT_FLYDOWN_WING_HIGH)
|
||||
ACT_FLYDOWN_WING_LOW, // Bay xuống thấp (should be ACT_FLYDOWN_WING_LOW)
|
||||
ACT_LANDON, // Hạ cánh (should be ACT_LAND_WING)
|
||||
|
||||
// 15
|
||||
ACT_TAKEOFF_SWORD, // Kiếm bay - cất cánh
|
||||
ACT_HANGINAIR_SWORD, // Kiếm bay - treo không trung
|
||||
ACT_FLY_SWORD, // Kiếm bay - tiến tới
|
||||
ACT_FLYDOWN_SWORD_HIGH, // Kiếm bay - rơi cao
|
||||
ACT_FLYDOWN_SWORD_LOW, // Kiếm bay - rơi thấp
|
||||
|
||||
// 20
|
||||
ACT_LANDON_SWORD, // Kiếm bay - hạ cánh
|
||||
ACT_SITDOWN, // Ngồi
|
||||
ACT_SITDOWN_LOOP, // Ngồi lặp lại
|
||||
ACT_STANDUP, // Đứng dậy
|
||||
ACT_WOUNDED, // Bị thương
|
||||
|
||||
// 25
|
||||
ACT_GROUNDDIE, // Chết trên mặt đất
|
||||
ACT_GROUNDDIE_LOOP, // Chết trên đất (loop)
|
||||
ACT_WATERDIE, // Chết trong nước
|
||||
ACT_WATERDIE_LOOP, // Chết trong nước (loop)
|
||||
ACT_AIRDIE_ST, // Chết trên không (bắt đầu)
|
||||
|
||||
// 30
|
||||
ACT_AIRDIE, // Chết trên không (loop rơi)
|
||||
ACT_AIRDIE_ED, // Chết trên không (chạm đất)
|
||||
ACT_AIRDIE_LAND_LOOP, // Chết rơi đất (loop)
|
||||
ACT_REVIVE, // Hồi sinh
|
||||
ACT_CUSTOMIZE, // Động tác tùy chỉnh
|
||||
|
||||
// 35
|
||||
ACT_STRIKEBACK, // Bị đánh lùi
|
||||
ACT_STRIKEDOWN, // Bị đánh ngã
|
||||
ACT_STRIKEDOWN_LOOP, // Bị đánh ngã (loop)
|
||||
ACT_STRIKEDOWN_STANDUP, // Bị đánh ngã rồi đứng dậy
|
||||
ACT_PICKUP, // Nhặt đồ
|
||||
|
||||
// 40
|
||||
ACT_PICKUP_LOOP, // Nhặt đồ (loop)
|
||||
ACT_PICKUP_STANDUP, // Nhặt đồ đứng dậy
|
||||
ACT_PICKUP_MATTER, // Nhặt vật thể
|
||||
ACT_GAPE, // Há miệng
|
||||
ACT_LOOKAROUND, // Nhìn quanh
|
||||
|
||||
// 45
|
||||
ACT_PLAYWEAPON, // Vung vũ khí
|
||||
ACT_EXP_WAVE, // Vẫy tay
|
||||
ACT_EXP_NOD, // Gật đầu
|
||||
ACT_EXP_SHAKEHEAD, // Lắc đầu
|
||||
ACT_EXP_SHRUG, // Nhún vai
|
||||
|
||||
// 50
|
||||
ACT_EXP_LAUGH, // Cười lớn
|
||||
ACT_EXP_ANGRY, // Tức giận
|
||||
ACT_EXP_STUN, // Choáng
|
||||
ACT_EXP_DEPRESSED, // Buồn bã
|
||||
ACT_EXP_KISSHAND, // Hôn tay
|
||||
|
||||
// 55
|
||||
ACT_EXP_SHY, // Ngại ngùng
|
||||
ACT_EXP_SALUTE, // Chào
|
||||
ACT_EXP_SITDOWN, // Ngồi xuống
|
||||
ACT_EXP_SITDOWN_LOOP, // Ngồi xuống (loop)
|
||||
ACT_EXP_SITDOWN_STANDUP, // Ngồi xuống rồi đứng dậy
|
||||
|
||||
// 60
|
||||
ACT_EXP_ASSAULT, // Tấn công
|
||||
ACT_EXP_THINK, // Suy nghĩ
|
||||
ACT_EXP_DEFIANCE, // Thách thức
|
||||
ACT_EXP_VICTORY, // Chiến thắng
|
||||
ACT_EXP_KISS, // Hôn
|
||||
|
||||
// 65
|
||||
ACT_EXP_KISS_LOOP, // Hôn (loop)
|
||||
ACT_EXP_KISS_END, // Kết thúc hôn
|
||||
ACT_ATTACK_1, // Tấn công 1
|
||||
ACT_ATTACK_2, // Tấn công 2
|
||||
ACT_ATTACK_3, // Tấn công 3
|
||||
|
||||
// 70
|
||||
ACT_ATTACK_4, // Tấn công 4
|
||||
ACT_ATTACK_TOSS, // Ném vũ khí
|
||||
ACT_TRICK_RUN, // Chiêu khi chạy
|
||||
ACT_TRICK_JUMP, // Chiêu khi nhảy
|
||||
ACT_FLY_GLIDE, // Lượn
|
||||
|
||||
// 75
|
||||
ACT_FLY_GLIDE_SWORD, // Kiếm bay - lượn
|
||||
ACT_EXP_FIGHT, // Tư thế chiến đấu
|
||||
ACT_EXP_ATTACK1, // Tấn công diễn xuất 1
|
||||
ACT_EXP_ATTACK2, // Tấn công diễn xuất 2
|
||||
ACT_EXP_ATTACK3, // Tấn công diễn xuất 3
|
||||
|
||||
// 80
|
||||
ACT_EXP_ATTACK4, // Tấn công diễn xuất 4
|
||||
ACT_EXP_DEFENCE, // Phòng thủ
|
||||
ACT_EXP_FALL, // Té ngã
|
||||
ACT_EXP_FALLONGROUND, // Ngã xuống đất
|
||||
ACT_EXP_LOOKAROUND, // Nhìn quanh
|
||||
|
||||
// 85
|
||||
ACT_EXP_DANCE, // Nhảy múa
|
||||
ACT_EXP_FASHIONWEAPON, // Động tác vũ khí thời trang
|
||||
ACT_USEITEM, // Dùng item
|
||||
ACT_USEITMELOOP, // Dùng item (loop)
|
||||
ACT_TWO_KISS, // Hôn đôi
|
||||
|
||||
// 90
|
||||
ACT_USING_TARGET_ITEM, // Dùng đạo cụ
|
||||
ACT_SWIM_FOR_MOVESKILL, // Bơi trong lúc dùng skill di chuyển
|
||||
|
||||
ACT_MAX,
|
||||
ACT_CASTSKILL // Chỉ là placeholder cho skill actions
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using UnityEngine;
|
||||
using static EC_Player;
|
||||
|
||||
public class PlayerMoveState : PlayerState
|
||||
{
|
||||
@@ -8,7 +9,7 @@ public class PlayerMoveState : PlayerState
|
||||
|
||||
public override void Enter()
|
||||
{
|
||||
|
||||
_characterCtrl.PlayAction((int)PLAYER_ACTION_TYPE.ACT_WALK,true,1,false);
|
||||
}
|
||||
|
||||
public override void Exit()
|
||||
|
||||
@@ -13,6 +13,7 @@ public class PlayerStateMachine
|
||||
return;
|
||||
}
|
||||
_state = state;
|
||||
_state.Enter();
|
||||
}
|
||||
|
||||
public void ChangeState(PlayerState state)
|
||||
|
||||
@@ -13,10 +13,8 @@ namespace BrewMonster.UI
|
||||
|
||||
public void InitScreen(List<RoleInfo> roleInfos, Action<RoleInfo> OnClickItemChar)
|
||||
{
|
||||
Logger.Log($"InitScreen {roleInfos.Count}");
|
||||
foreach(RoleInfo info in roleInfos)
|
||||
{
|
||||
Logger.Log($"Role Name {info.roleid}");
|
||||
CharacterItemUI item = Instantiate(characterItemPrefab, parentItems).GetComponent<CharacterItemUI>();
|
||||
item.InitItem(info, OnClickItemChar);
|
||||
}
|
||||
|
||||
@@ -36,10 +36,8 @@ GraphicsSettings:
|
||||
- {fileID: 10783, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_PreloadedShaders: []
|
||||
m_PreloadShadersBatchTimeLimit: -1
|
||||
m_SpritesDefaultMaterial: {fileID: 10754, guid: 0000000000000000f000000000000000,
|
||||
type: 0}
|
||||
m_CustomRenderPipeline: {fileID: 11400000, guid: 4b83569d67af61e458304325a23e5dfd,
|
||||
type: 2}
|
||||
m_SpritesDefaultMaterial: {fileID: 10754, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_CustomRenderPipeline: {fileID: 11400000, guid: 4b83569d67af61e458304325a23e5dfd, type: 2}
|
||||
m_TransparencySortMode: 0
|
||||
m_TransparencySortAxis: {x: 0, y: 0, z: 1}
|
||||
m_DefaultRenderingPath: 1
|
||||
@@ -60,9 +58,8 @@ GraphicsSettings:
|
||||
m_FogKeepExp2: 1
|
||||
m_AlbedoSwatchInfos: []
|
||||
m_RenderPipelineGlobalSettingsMap:
|
||||
UnityEngine.Rendering.Universal.UniversalRenderPipeline: {fileID: 11400000, guid: 18dc0cd2c080841dea60987a38ce93fa,
|
||||
type: 2}
|
||||
m_LightsUseLinearIntensity: 1
|
||||
UnityEngine.Rendering.Universal.UniversalRenderPipeline: {fileID: 11400000, guid: 18dc0cd2c080841dea60987a38ce93fa, type: 2}
|
||||
m_LightsUseLinearIntensity: 0
|
||||
m_LightsUseColorTemperature: 1
|
||||
m_LogWhenShaderIsCompiled: 0
|
||||
m_LightProbeOutsideHullStrategy: 0
|
||||
|
||||
Reference in New Issue
Block a user