Merge pull request 'feature/HostAttack_Hoang' (#26) from feature/HostAttack_Hoang into develop

Reviewed-on: https://git.brew.monster/Unity/perfect-world-unity/pulls/26
This commit is contained in:
hoangvd
2025-10-13 11:13:33 +00:00
64 changed files with 1423 additions and 187 deletions
@@ -1504,6 +1504,15 @@ namespace ModelRenderer.Scripts.GameData
}
break;
// TODO: Add other id spaces here.
case ID_SPACE.ID_SPACE_CONFIG:
foreach (var item in config_id_data_type_map)
{
if (item.Value == dataType)
{
return item.Key;
}
}
break;
default:
return 0;
}
@@ -0,0 +1,24 @@
using BrewMonster;
using CSNetwork.GPDataType;
using System;
using UnityEngine;
public class CECGameRun
{
private CECWorld m_pWorld;
public CECWorld GetWorld() { return m_pWorld; }
public bool StartGame(int idInst, Vector3 vHostPos)
{
if (!JumpToInstance(idInst, vHostPos))
{
BMLogger.LogError ( "CECGameRun::StartGame, Failed to create game world.");
return false;
}
return true;
}
private bool JumpToInstance(int idInst, Vector3 vHostPos, int iParallelWorldID = 0)
{
return true;
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 923b4102fc6857a4e94d7a662b2e6e1a
@@ -8,6 +8,7 @@ namespace BrewMonster.Network
#region Fields
private static ATaskTemplMan m_pTaskMan; // Task template manager
private static elementdataman m_pElementDataMan; // global element templates manager
private static CECGameRun m_pGameRun; // Game running object
#endregion
#region Properties
@@ -29,8 +30,15 @@ namespace BrewMonster.Network
Debug.LogError("[Dat]- CECGame::Init, Storage task Init Failed!");
return false;
}
m_pGameRun = new CECGameRun();
if (m_pGameRun == null)
{
BMLogger.LogError("CECGame::Init");
return false;
}
return true;
}
public static CECGameRun GetGameRun() { return m_pGameRun; }
#endregion
}
}
@@ -0,0 +1,357 @@
using BrewMonster;
using CSNetwork.GPDataType;
using System;
using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;
using static CECAttacksMan;
public class CECAttacksMan : MonoSingleton<CECAttacksMan>
{
private readonly LinkedList<CECAttackEvent> m_AttackLinkedList = new LinkedList<CECAttackEvent>();
private void Update()
{
var node = m_AttackLinkedList.First;
while (node != null)
{
var next = node.Next;
if (node.Value.m_bFinished)
m_AttackLinkedList.Remove(node);
else node.Value.Tick((uint)(Time.deltaTime * 1000));
node = next;
}
}
public CECAttackerEvents FindAttackByAttacker(int idHost)
{
CECAttackerEvents result = new CECAttackerEvents();
foreach (var attack in m_AttackLinkedList)
{
if (attack.m_idHost == idHost)
{
result.Add(attack);
}
}
return result;
}
public CECAttackEvent AddMeleeAttack(int idHost, int idTarget, int idWeapon, uint dwModifier, int nDamage, int nTimeFly = 10)
{
var newEvent = new CECAttackEvent(
this,
idHost,
0, // idCastTarget
idTarget,
idWeapon,
0, // idSkill
0, // nSkillLevel
dwModifier,
nDamage,
200, // timeToBeFired
nTimeFly // timeToDoDamage
);
m_AttackLinkedList.AddLast(newEvent);
newEvent.UpdateTargetFlag();
return m_AttackLinkedList.Last.Value;
}
public CECAttackEvent AddSkillAttack(int idHost, int idCastTarget, int idTarget, int idWeapon, int idSkill, int nSkillLevel, uint dwModifier, int nDamage)
{
var newEvent = new CECAttackEvent(
this,
idHost,
idCastTarget,
idTarget,
idWeapon,
idSkill,
nSkillLevel,
dwModifier,
nDamage,
200, // timeToBeFired
1000 // timeToDoDamage
);
m_AttackLinkedList.AddLast(newEvent);
newEvent.UpdateTargetFlag();
return m_AttackLinkedList.Last.Value;
}
// === thêm tạm để code có thể compile ===
public void AddAttack(CECAttackEvent evt)
{
m_AttackLinkedList.AddLast(evt);
}
public class TARGET_DATA
{
public int idTarget;
public uint dwModifier;
public int nDamage;
}
}
public class CECAttackEvent
{
public CECAttacksMan? m_pManager;
public bool m_bSignaled;
public bool m_bDoFired;
public bool m_bDoDamaged;
public bool m_bFinished;
public uint m_timeLived;
public uint m_timeToBeFired;
public uint m_timeToDoDamage;
public int m_idHost;
public int m_idCastTarget;
public List<TARGET_DATA> m_targets = new List<TARGET_DATA>();
public int m_idWeapon;
public int m_idSkill;
public int m_nSkillLevel;
public int m_nSkillSection;
public CECAttackEvent() { }
public CECAttackEvent(CECAttacksMan? pManager, int idHost, int idCastTarget, int idTarget,
int idWeapon, int idSkill, int nSkillLevel, uint dwModifier,
int nDamage, int nTimeToBeFired, int nTimeToDoDamage)
{
m_pManager = pManager;
m_idHost = idHost;
m_idCastTarget = idCastTarget;
m_idWeapon = idWeapon;
m_idSkill = idSkill;
m_nSkillLevel = nSkillLevel;
m_timeToBeFired = (uint)nTimeToBeFired;
m_timeToDoDamage = (uint)nTimeToDoDamage;
AddTarget(idTarget, dwModifier, nDamage);
}
public bool Tick(uint dwDeltaTime)
{
m_timeLived += dwDeltaTime;
if (!m_bSignaled)
{
if (m_timeLived > 3500)
{
// too long time, this event will be deleted now
m_bFinished = true;
//DoFire();
DoDamage();
}
return true;
}
else
{
if (m_timeToBeFired != 0)
{
if (m_timeToBeFired <= dwDeltaTime)
{
m_timeToBeFired = 0;
// Fire here
//DoFire();
}
else
m_timeToBeFired -= dwDeltaTime;
}
else if (m_timeToDoDamage != 0)
{
if (m_timeToDoDamage <= dwDeltaTime)
{
m_timeToDoDamage = 0;
// Do damage here
DoDamage();
}
else
m_timeToDoDamage -= dwDeltaTime;
}
}
return true;
}
private bool DoDamage()
{
m_bDoDamaged = true;
m_bFinished = true;
/* CECGameRun pGameRun = g_pGame-GetGameRun();
int idHostPlayer = pGameRun->GetHostPlayer()->GetCharacterID();*/
// Get host name
/* ACString strHostName;
CECObject* pHostObject = pGameRun->GetWorld()->GetObject(m_idHost, 0);
if (pHostObject)
{
if (ISNPCID(m_idHost))
strHostName = ((CECNPC*)pHostObject)->GetName();
else if (ISPLAYERID(m_idHost))
strHostName = GetPlayerName((CECPlayer*)pHostObject);
}*/
int nNumTargets = m_targets.Count;
for (int i = 0; i < nNumTargets; i++)
{
TARGET_DATA data = m_targets[i];
int idTarget = data.idTarget;
string strName;
if (GPDataTypeHelper.ISNPCID(idTarget))
{
CECNPC pNPC = null;
if ((data.dwModifier & (uint)MOD.MOD_SUCCESS) != 0)
pNPC = EC_ManMessageMono.Instance._CECNPCMan.GetNPCFromAll(idTarget);
else
{
pNPC = EC_ManMessageMono.Instance._CECNPCMan.GetNPCFromAll(idTarget);
if (!pNPC)
return true;
//strName = pNPC->GetNameToShow();
}
if (!pNPC)
return true;
pNPC.Damaged(data.nDamage, data.dwModifier);
}
else if (GPDataTypeHelper.ISPLAYERID(idTarget))
{
/* CECPlayer* pPlayer = pGameRun->GetWorld()->GetPlayerMan()->GetPlayer(idTarget);
if (!pPlayer)
return true;
strName = GetPlayerName(pPlayer);
pPlayer->Damaged(data.nDamage, data.dwModifier, m_idSkill);*/
}
/* if (data.nDamage > 0)
{
if (m_idHost == idHostPlayer)
{
if (!strName.IsEmpty())
pGameRun->AddFixedChannelMsg(FIXMSG_DODAMAGE, GP_CHAT_DAMAGE, strName, data.nDamage);
}
else if (data.idTarget == idHostPlayer)
{
if (!strHostName.IsEmpty())
pGameRun->AddFixedChannelMsg(FIXMSG_BEDAMAGED, GP_CHAT_DAMAGE, strHostName, data.nDamage);
}
}*/
}
return true;
}
public bool AddTarget(int idTarget, uint dwModifier, int nDamage)
{
m_targets.Add(new TARGET_DATA
{
idTarget = idTarget,
dwModifier = dwModifier,
nDamage = nDamage
});
return true;
}
public bool UpdateTargetFlag()
{
// update all targets' bAboutToDie flag
int nNumTargets = m_targets.Count;
for (int i = 0; i < nNumTargets; i++)
{
TARGET_DATA data = m_targets[i];
/*
if( data.dwModifier & MOD_DEADLYSTRIKE )
{
int idTarget = data.idTarget;
if (ISNPCID(idTarget))
{
CECNPC* pNPC = g_pGame->GetGameRun()->GetWorld()->GetNPCMan()->GetNPC(idTarget);
if (!pNPC)
return true;
pNPC->SetAboutToDie(true);
}
else if (ISPLAYERID(idTarget))
{
CECPlayer* pPlayer = g_pGame->GetGameRun()->GetWorld()->GetPlayerMan()->GetPlayer(idTarget);
if (!pPlayer)
return true;
pPlayer->SetAboutToDie(true);
}
}*/
}
return true;
}
}
public class CECAttackerEvents
{
private readonly List<CECAttackEvent> m_list = new List<CECAttackEvent>();
public void Add(CECAttackEvent? evt)
{
if (evt != null)
m_list.Add(evt);
}
public bool IsEmpty() => m_list.Count == 0;
public int Count() => m_list.Count;
public CECAttackEvent? Find(int idSkill = 0, int nSkillSection = 0)
{
foreach (var evt in m_list)
{
if (evt.m_idSkill == idSkill && evt.m_nSkillSection == nSkillSection)
return evt;
}
return null;
}
public void Signal()
{
foreach (var evt in m_list)
evt.m_bSignaled = true;
m_list.Clear();
}
public static implicit operator bool(CECAttackerEvents events)
{
return !events.IsEmpty();
}
}
enum MOD
{
MOD_PHYSIC_ATTACK_RUNE = 0x0001, // ÎïÀí¹¥»÷ÓÅ»¯·ûÉúЧ
MOD_MAGIC_ATTACK_RUNE = 0x0002, // ·¨Êõ¹¥»÷ÓÅ»¯·ûÉúЧ
MOD_PHYSIC_DEFENCE_RUNE = 0x0004, // ÎïÀí·ÀÓùÓÅ»¯·ûÉúЧ
MOD_MAGIC_DEFENCE_RUNE = 0x0008, // ·¨Êõ·ÀÓùÓÅ»¯·ûÉúЧ
MOD_CRITICAL_STRIKE = 0x0010, // ±¬»÷
MOD_RETORT = 0x0020, // ·´Õð
MOD_NULLITY = 0x0040, // ÎÞЧ¹¥»÷
MOD_IMMUNE = 0x0080, // ÃâÒßÁ˴˴ι¥»÷£¬ÓÅÏȼ¶¸ßÓÚÎÞЧ
MOD_ENCHANT_FAILED = 0x0100, // enchant ʧ°Ü
MOD_SUCCESS = 0x0200, // ³É¹¦
MOD_DODGE_DAMAGE = 0x0400, // É˺¦¶ãÉÁ
MOD_DODGE_DEBUFF = 0x0800, // ״̬¶ãÉÁ
MOD_ATTACK_AURA = 0x1000, // ¹â»·¹¥»÷
MOD_REBOUND = 0x2000, // ·´µ¯
MOD_BEAT_BACK = 0x4000, // ·´»÷
};
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 92009c5b4b0fd894790865cf674545fa
@@ -6,6 +6,7 @@ using System;
using System.Buffers.Binary;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using Unity.VisualScripting;
using UnityEngine;
public class CECNPCMan : CECObject, IMsgHandler
@@ -203,6 +204,22 @@ public class CECNPCMan : CECObject, IMsgHandler
return npc;
}
public CECNPC GetNPCFromAll(int nid)
{
CECNPC pNPC = GetNPC(nid);
if (pNPC)
return pNPC;
// Search from disappear array ?
/*for (int i = 0; i < m_aDisappearNPCs.GetSize(); i++)
{
CECNPC* pNPC = m_aDisappearNPCs[i];
if (pNPC->GetNPCID() == nid)
return pNPC;
}*/
return null;
}
public CECNPC CreateNPC(info_npc Info, bool bBornInSight, ReadOnlySpan<byte> packet, int infoOffset)
{
CECNPC pNPC = null;
@@ -0,0 +1,85 @@
using UnityEngine;
using System.Collections.Generic;
using TMPro;
using DG.Tweening; // cần DOTween
public class DamageTextManager : MonoBehaviour
{
public static DamageTextManager Instance { get; private set; }
[Header("Prefab")]
[SerializeField] private TextMeshPro damageTextPrefab;
[Header("Settings")]
[SerializeField] private int poolSize = 20;
[SerializeField] private Vector3 offset = new Vector3(0, 2f, 0);
[SerializeField] private float riseDistance = 1.5f;
[SerializeField] private float riseDuration = 0.8f;
private readonly Queue<TextMeshPro> pool = new();
private void Awake()
{
// Singleton
if (Instance != null && Instance != this)
{
Destroy(gameObject);
return;
}
Instance = this;
DontDestroyOnLoad(gameObject);
// Tạo sẵn pool
for (int i = 0; i < poolSize; i++)
{
var textObj = Instantiate(damageTextPrefab, transform);
textObj.gameObject.SetActive(false);
pool.Enqueue(textObj);
}
}
/// <summary>
/// Gọi để spawn text damage
/// </summary>
public void SpawnDamage(Vector3 worldPos, int damage, Color color, float scale = 1f)
{
var text = GetFromPool();
text.text = damage.ToString();
text.color = color;
text.fontSize = 6;
text.transform.localScale = Vector3.one * scale;
Vector3 startPos = worldPos + offset;
text.transform.position = startPos;
text.gameObject.SetActive(true);
// Hiệu ứng bay lên + mờ dần
text.transform.DOMoveY(startPos.y + riseDistance, riseDuration).SetEase(Ease.OutQuad);
text.DOFade(0f, riseDuration)
.SetEase(Ease.InQuad)
.OnComplete(() =>
{
text.alpha = 1f;
text.gameObject.SetActive(false);
ReturnToPool(text);
});
}
private TextMeshPro GetFromPool()
{
if (pool.Count > 0)
{
return pool.Dequeue();
}
// Nếu hết pool, tạo thêm
var text = Instantiate(damageTextPrefab, transform);
text.gameObject.SetActive(false);
return text;
}
private void ReturnToPool(TextMeshPro text)
{
pool.Enqueue(text);
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: e7981b037b60f4a4989ff59265a308ad
@@ -148,7 +148,7 @@ class CECHPWorkMelee : CECHPWork
protected virtual void OnFirstTick()
{
m_pHost.m_iMoveMode = (int)MoveMode.MOVE_STAND;
m_pHost.PlayAction((int)EC_Player.PLAYER_ACTION_TYPE.ACT_ATTACK_1 + Random.Range(0, 3), true, 200, false);
m_pHost.PlayAction((int)CECPlayer.PLAYER_ACTION_TYPE.ACT_ATTACK_1 + Random.Range(0, 3), true, 200, false);
m_idTarget = m_pHost.m_idSelTarget;
}
@@ -139,7 +139,7 @@ public abstract class CECTracedObject
}
else
{
EC_Player pPlayer = pObject.GetComponent<CECHostPlayer>();
CECPlayer pPlayer = pObject.GetComponent<CECHostPlayer>();
fTouchRadius = pPlayer.GetTouchRadius();
}
return m_pHost.CanTouchTarget(vHostPos, vTargetPos, fTouchRadius, iTouchReason, fMaxCut);
@@ -384,7 +384,7 @@ public class CECTracedPlayer : CECTracedObject
{
return true;
}
EC_Player pPlayer = GetTargetObject() as EC_Player;
CECPlayer pPlayer = GetTargetObject() as CECPlayer;
if (pPlayer.IsElsePlayer())
{
if (pPlayer.IsDead())
@@ -615,10 +615,10 @@ public class CECHPWorkTrace : CECHPWork
{
// Continue tracing object
float fDeltaTime = dwDeltaTime /** 0.001f*/;
if (m_pHost.m_iMoveEnv == EC_Player.Move_environment.MOVEENV_GROUND)
if (m_pHost.m_iMoveEnv == CECPlayer.Move_environment.MOVEENV_GROUND)
{
// Play appropriate actions
if (!m_pHost.IsJumping() && !m_pHost.IsPlayingAction((int)EC_Player.PLAYER_ACTION_TYPE.ACT_TRICK_RUN) &&
if (!m_pHost.IsJumping() && !m_pHost.IsPlayingAction((int)CECPlayer.PLAYER_ACTION_TYPE.ACT_TRICK_RUN) &&
m_pHost.m_iMoveMode != (int)MoveMode.MOVE_SLIDE)
{
int iAction = m_pHost.GetMoveStandAction(true);
@@ -810,7 +810,7 @@ public class CECHPWorkTrace : CECHPWork
if (m_pHost.m_iMoveMode == (int)MoveMode.MOVE_SLIDE)
{
m_pHost.PlayAction((int)EC_Player.PLAYER_ACTION_TYPE.ACT_JUMP_LOOP, false, 200, false);
m_pHost.PlayAction((int)CECPlayer.PLAYER_ACTION_TYPE.ACT_JUMP_LOOP, false, 200, false);
// This will cause stop moming after we slide down.
A3DVECTOR3 vDir = vTargetPos - vCurPos;
@@ -183,7 +183,7 @@ namespace PerfectWorld.Scripts.Managers
// For equipping, we need to find an empty equipment slot
// Use the new method that checks for available slots (especially for finger items)
byte equipLocation = EC_IvtrType.GetAvailableEquipLocationForItem(currentSelectedItem.TemplateId);
if (equipLocation >= (byte)EC_IvtrType.IndexOfIteminEquipmentInventory.SIZE_EQUIPIVTR)
if (equipLocation >= (byte)IndexOfIteminEquipmentInventory.SIZE_EQUIPIVTR)
{
Debug.LogWarning($"[InventoryUI] Could not determine equip location for item {currentSelectedItem.TemplateId}");
return;
@@ -5,43 +5,54 @@ using BrewMonster;
namespace PerfectWorld.Scripts.Managers
{
public enum IndexOfIteminEquipmentInventory : byte
{
EQUIPIVTR_WEAPON = 0,
EQUIPIVTR_HEAD = 1,
EQUIPIVTR_NECK = 2,
EQUIPIVTR_SHOULDER = 3,
EQUIPIVTR_BODY = 4,
EQUIPIVTR_WAIST = 5,
EQUIPIVTR_LEG = 6,
EQUIPIVTR_FOOT = 7,
EQUIPIVTR_WRIST = 8,
EQUIPIVTR_FINGER1 = 9,
EQUIPIVTR_FINGER2 = 10,
EQUIPIVTR_PROJECTILE = 11,
EQUIPIVTR_FLYSWORD = 12,
EQUIPIVTR_FASHION_BODY = 13,
EQUIPIVTR_FASHION_LEG = 14,
EQUIPIVTR_FASHION_FOOT = 15,
EQUIPIVTR_FASHION_WRIST = 16,
EQUIPIVTR_RUNE = 17,
EQUIPIVTR_BIBLE = 18,
EQUIPIVTR_SPEAKER = 19,
EQUIPIVTR_AUTOHP = 20,
EQUIPIVTR_AUTOMP = 21,
EQUIPIVTR_POCKET = 22,
EQUIPIVTR_GOBLIN = 23,
EQUIPIVTR_CERTIFICATE = 24,
EQUIPIVTR_FASHION_HEAD = 25,
EQUIPIVTR_FORCE_TOKEN = 26,
EQUIPIVTR_DYNSKILLEQUIP1 = 27,
EQUIPIVTR_DYNSKILLEQUIP2 = 28,
EQUIPIVTR_FASHION_WEAPON = 29,
SIZE_EQUIPIVTR = 30,
EQUIPIVTR_UNUSED1 = SIZE_EQUIPIVTR,
EQUIPIVTR_UNUSED2 = 31,
EQUIPIVTR_GENERALCARD1,
EQUIPIVTR_GENERALCARD2,
EQUIPIVTR_GENERALCARD3,
EQUIPIVTR_GENERALCARD4 = 35,
EQUIPIVTR_GENERALCARD5,
EQUIPIVTR_GENERALCARD6,
SIZE_ALL_EQUIPIVTR,
SIZE_GENERALCARD_EQUIPIVTR = SIZE_ALL_EQUIPIVTR - EQUIPIVTR_GENERALCARD1,
}
public static class EC_IvtrType
{
public enum IndexOfIteminEquipmentInventory : byte
{
EQUIPIVTR_WEAPON = 0,
EQUIPIVTR_HEAD = 1,
EQUIPIVTR_NECK = 2,
EQUIPIVTR_SHOULDER = 3,
EQUIPIVTR_BODY = 4,
EQUIPIVTR_WAIST = 5,
EQUIPIVTR_LEG = 6,
EQUIPIVTR_FOOT = 7,
EQUIPIVTR_WRIST = 8,
EQUIPIVTR_FINGER1 = 9,
EQUIPIVTR_FINGER2 = 10,
EQUIPIVTR_PROJECTILE = 11,
EQUIPIVTR_FLYSWORD = 12,
EQUIPIVTR_FASHION_BODY = 13,
EQUIPIVTR_FASHION_LEG = 14,
EQUIPIVTR_FASHION_FOOT = 15,
EQUIPIVTR_FASHION_WRIST = 16,
EQUIPIVTR_RUNE = 17,
EQUIPIVTR_BIBLE = 18,
EQUIPIVTR_SPEAKER = 19,
EQUIPIVTR_AUTOHP = 20,
EQUIPIVTR_AUTOMP = 21,
EQUIPIVTR_POCKET = 22,
EQUIPIVTR_GOBLIN = 23,
EQUIPIVTR_CERTIFICATE = 24,
EQUIPIVTR_FASHION_HEAD = 25,
EQUIPIVTR_FORCE_TOKEN = 26,
EQUIPIVTR_DYNSKILLEQUIP1 = 27,
EQUIPIVTR_DYNSKILLEQUIP2 = 28,
EQUIPIVTR_FASHION_WEAPON = 29,
SIZE_EQUIPIVTR = 30,
}
public static byte GetEquipLocationForItem(int templateId)
{
try
@@ -470,7 +470,7 @@ namespace PerfectWorld.Scripts.Managers
}
// Get a player (may be host or else player) by id
public EC_Player GetPlayer(int cid, uint dwBornStamp = 0)
public CECPlayer GetPlayer(int cid, uint dwBornStamp = 0)
{
CECHostPlayer pHost = GetHostPlayer();
if (pHost && pHost.GetCharacterID() == cid)
@@ -185,7 +185,7 @@ public class CECObject : MonoBehaviour
return 0;
if (pObject.IsPlayer())
return ((EC_Player)pObject).GetCharacterID();
return ((CECPlayer)pObject).GetCharacterID();
else if (pObject.IsNPC())
return ((CECNPC)pObject).GetNPCID();
//else if (pObject.IsMatter())
@@ -85,7 +85,7 @@ public class CECHostMove
float fSpeed = 0f;
switch (m_pHost.GetMoveEnv())
{
case EC_Player.Move_environment.MOVEENV_AIR:
case CECPlayer.Move_environment.MOVEENV_AIR:
iMoveMode |= (int)GPMoveMode.GP_MOVE_AIR;
fSpeed = m_pHost.GetFlySpeed();
@@ -1,26 +1,34 @@
using BrewMonster;
using CSNetwork.GPDataType;
using ModelRenderer.Scripts.GameData;
using PerfectWorld.Scripts.Managers;
using PerfectWorld.Scripts.Player;
using System;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;
public abstract class EC_Player : CECObject
public abstract class CECPlayer : CECObject
{
private static PLAYER_ACTION[] _default_actions;
private static PLAYER_ACTION[] _turning_actions;
PLAYER_ACTION[] m_PlayerActions;
[SerializeField] internal INFO m_PlayerInfo;
protected GameObject m_pPlayerModel;
protected GameObject _pPlayerModel;
protected float rotationSpeed = 5;
internal int m_iMoveMode; // Player's move mode
internal int m_idSelTarget; // Ñ¡ÖÐÄ¿±êµÄID
uint m_dwStates; // Player's basic states
internal int m_idSelTarget;
protected int m_iShape; // Ñ¡ÖÐÄ¿±êµÄID
protected uint m_dwStates; // Player's basic states
protected uint m_uAttackType;
protected int[] m_aEquips;
protected ROLEEXTPROP m_ExtProps; // Extend properties
protected float m_fTouchRad = 0.3f; // Touch radius
protected int m_iFashionWeaponType;
protected float m_fTouchRad = 0.3f; // Touch radius
protected bool m_bWeaponAttached;
protected int m_iBattleCamp = Player_camp_in_battle.GP_BATTLE_CAMP_NONE; // Battle this player belongs to
byte m_factionPVPMask; // pvp mask
byte m_factionPVPMask; // pvp mask
protected uint m_dwResFlags; // pvp mask
protected ROLEBASICPROP m_BasicProps;
public int m_iMoveEnv = Move_environment.MOVEENV_GROUND; // Move environment
public bool m_bWalkRun;
@@ -28,7 +36,12 @@ public abstract class EC_Player : CECObject
public A3DAABB m_aabb = new A3DAABB(); // Player's aabb£¬ÓÃÓÚÏÔʾµÄaabb£¬ÊÜËõ·ÅÓ°Ïì
public int m_iProfession; // Profession
public float m_fScaleBySkill;
public int m_iGender; // Gender
public int m_iGender; // Gender
protected bool m_bFashionMode;
protected int NUM_WEAPON_TYPE = 15;
public MOVECONST m_MoveConst; // Const used when moving control
public MOVECONST[] aMoveConsts = new MOVECONST[PROFESSION.NUM_PROFESSION * GENDER.NUM_GENDER]
@@ -103,6 +116,12 @@ public abstract class EC_Player : CECObject
protected void Awake()
{
m_PlayerActions = _default_actions;
m_iShape = 0;
m_aEquips = new int[(int)IndexOfIteminEquipmentInventory.SIZE_ALL_EQUIPIVTR];
}
public void SetUpPlayer()
{
m_dwResFlags = 0;
}
public void SetPlayerInfor(INFO playinfo)
{
@@ -127,9 +146,12 @@ public abstract class EC_Player : CECObject
BuildActionList();
}
public bool IsDead(){ return (m_dwStates & PlayerNPCState.GP_STATE_CORPSE) != 0; }
public bool IsDead() { return (m_dwStates & PlayerNPCState.GP_STATE_CORPSE) != 0; }
public bool IsValidAction(int iIndex) { return (iIndex >= 0 && iIndex < (int)PLAYER_ACTION_TYPE.ACT_MAX) ? true : false; }
public int GetCharacterID() { return m_PlayerInfo.cid; }
private static void BuildActionList()
{
if (_default_actions == null)
@@ -233,6 +255,7 @@ public abstract class EC_Player : CECObject
public PLAYER_ACTION_TYPE type;
public PLAYER_ACTION_INFO_CONFIG data;
};
public INFO GetPlayerInfo() { return m_PlayerInfo; }
public enum PLAYER_ACTION_TYPE
{
// 0
@@ -368,8 +391,301 @@ public abstract class EC_Player : CECObject
ACT_MAX,
ACT_CASTSKILL // Chỉ là placeholder cho skill actions
}
public void PlayAttackEffect(int idTarget, int idSkill, int skillLevel, int nDamage,
uint dwModifier, int nAttackSpeed, ref int piAttackTime/* NULL */, int nSection = 0)
{
/* if (!IsAllResReady())
return;*/
public float GetTouchRadius(){ return m_fTouchRad; }
if (idSkill == 0)
{
int idWeapon = IsShapeChanged() ? 0 : GetWeaponID();
int nTimeFly = 10;
if (idWeapon != 0)
{
// ¿´¿´ÊDz»ÊÇÔ¶³ÌÎäÆ÷
DATA_TYPE dt = default;
WEAPON_ESSENCE? pWeapon = (WEAPON_ESSENCE)ElementDataManProvider.GetElementDataMan().get_data_ptr((uint)idWeapon, ID_SPACE.ID_SPACE_ESSENCE, ref dt);
if (dt == DATA_TYPE.DT_WEAPON_ESSENCE && pWeapon != null && pWeapon.Value.require_projectile != 0)
{
nTimeFly = 700;
if (m_aEquips[(int)IndexOfIteminEquipmentInventory.EQUIPIVTR_PROJECTILE] != 0)
idWeapon = m_aEquips[(int)IndexOfIteminEquipmentInventory.EQUIPIVTR_PROJECTILE];
}
}
if (CECAttacksMan.Instance.FindAttackByAttacker(GetPlayerInfo().cid))
{
// Unity animation làm hộ r
//ClearComActFlagAllRankNodes(true);
}
// melee attack
CECAttackEvent pAttack = CECAttacksMan.Instance.AddMeleeAttack(
GetPlayerInfo().cid, idTarget, idWeapon, dwModifier, nDamage, nTimeFly);
if (pAttack != null)
{
if (!IsDead() && (dwModifier & (uint)MOD.MOD_RETORT) == 0
&& (dwModifier & (uint)MOD.MOD_ATTACK_AURA) == 0
&& PlayAttackAction(nAttackSpeed, out piAttackTime, ref pAttack.m_bSignaled)
&& (dwModifier & (uint)MOD.MOD_BEAT_BACK) == 0)
{
}
else
{
pAttack.m_bSignaled = true;
}
}
}
else
{
/* if (skillLevel == 0)
{
if (m_pCurSkill)
skillLevel = m_pCurSkill->GetSkillLevel();
else
skillLevel = 1;
}
CECAttackEvent* pAttack = NULL;
// first try to find if there is already a skill attack event in attackman
CECAttackerEvents attackerEvents = g_pGame->GetGameRun()->GetWorld()->GetAttacksMan()->FindAttackByAttacker(GetPlayerInfo().cid);
if (attackerEvents)
{
if (CECAttackEvent * pAttack = attackerEvents.Find(idSkill, nSection))
{
// Ãæ¹¥»÷µÄ·ÇµÚÒ»´ÎÉ˺¦ÏûÏ¢
pAttack->AddTarget(idTarget, dwModifier, nDamage);
goto EXIT;
}
else
{
attackerEvents.Signal();
}
}
if (GNET::ElementSkill::IsGoblinSkill(idSkill) &&
GNET::ElementSkill::GetType(idSkill) == 2)
{
pAttack = g_pGame->GetGameRun()->GetWorld()->GetAttacksMan()->AddSkillAttack(
GetPlayerInfo().cid, GetPlayerInfo().cid, idTarget, GetWeaponID(), idSkill, skillLevel, dwModifier, nDamage);
}
else
{
// begin a skill attack
pAttack = g_pGame->GetGameRun()->GetWorld()->GetAttacksMan()->AddSkillAttack(
GetPlayerInfo().cid, m_idCurSkillTarget, idTarget, GetWeaponID(), idSkill, skillLevel, dwModifier, nDamage);
}
if (pAttack)
{
pAttack->SetSkillSection(nSection);
if (!IsDead() && (dwModifier & CECAttackEvent::MOD_RETORT) == 0
&& (dwModifier & CECAttackEvent::MOD_ATTACK_AURA) == 0
&& PlaySkillAttackAction(idSkill, nAttackSpeed, NULL, nSection, &pAttack->m_bSignaled)
&& (dwModifier & CECAttackEvent::MOD_BEAT_BACK) == 0)
{
}
else
{
pAttack->m_bSignaled = true;
}
}
EXIT:
// For skill attacking, time is always set to 0
if (piAttackTime)
*piAttackTime = 0;*/
}
}
public bool PlayAttackAction(int nAttackSpeed, out int attackTime, ref bool pActFlag)
{
attackTime = 0;
if (_pPlayerModel == null)
return false;
int nRand = UnityEngine.Random.Range(0, 4);
string szAct = string.Empty;
//int weapon_type = GetShowingWeaponType();
int nTime1 = 0, nTime2 = 0;
int iAction = (int)PLAYER_ACTION_TYPE.ACT_ATTACK_1 + nRand;
PLAYER_ACTION action = m_PlayerActions[iAction];
if (string.IsNullOrEmpty(action.data.ActionPrefix))
return false;
ShowWeaponByConfig(action.data);
/* var pRightHandWeapon = GetRightHandWeapon();
bool bHideFX = !CECOptimize.Instance.GFX.CanShowAttack(GetCharacterID(), GetClassID());*/
// ==============================
// Ground Attack
// ==============================
if (GetMoveEnv() == (int)MoveEnvironment.MOVEENV_GROUND)
{
// “起” 动作(挥起)
szAct = EC_Utility.BuildActionName(action, 0, "Æð");
EventBus.PublishChannel(m_PlayerInfo.cid, new PlayActionEvent(szAct));
szAct = EC_Utility.BuildActionName(action, 0, "Âä");
EventBus.PublishChannel(m_PlayerInfo.cid, new QueueActionEvent(szAct));
//PlayNonSkillActionWithName(iAction, szAct, true, 200, true, ref pActFlag, COMACT_FLAG_MODE_ONCE_MULTIIGNOREGFX);
/*
if (pRightHandWeapon != null && IsUsingMagicWeapon())
pRightHandWeapon.PlayActionByName(_GenWeaponActionName(szAct, m_iGender), 1.0f, true, 200, true, iAction, bHideFX);
nTime1 = _pPlayerModel.GetComActTimeSpanByName(szAct);
// “收” 动作(挥下)
szAct = $"{action.data.action_prefix}_{action.data.action_weapon_suffix[weapon_type].suffix}Âä";
QueueNonSkillActionWithName(iAction, szAct, 0, false, bHideFX);
if (pRightHandWeapon != null && IsUsingMagicWeapon())
pRightHandWeapon.QueueAction(_GenWeaponActionName(szAct, m_iGender), 0, iAction, false, false, bHideFX);
nTime2 = _pPlayerModel.GetComActTimeSpanByName(szAct);*/
}
// ==============================
// Air Attack
// ==============================
else
{
/*string szActionMiddleName;
if ((m_wingType == WINGTYPE_WING && IsFlying()) ||
GetProfession() == PROF_ANGEL ||
GetProfession() == PROF_ARCHOR ||
GetProfession() == PROF_MONK ||
GetProfession() == PROF_GHOST)
{
szActionMiddleName = "¿ÕÖгá°ò"; // tấn công trên không
}
else
{
szActionMiddleName = "¿ÕÖзɽ£"; // rơi xuống hoặc bay
}
szAct = $"{action.data.action_prefix}_{szActionMiddleName}_{action.data.action_weapon_suffix[weapon_type].suffix}Æð";
PlayNonSkillActionWithName(iAction, szAct, true, 200, bHideFX, ref pActFlag, COMACT_FLAG_MODE_ONCE_MULTIIGNOREGFX);
if (pRightHandWeapon != null && IsUsingMagicWeapon())
pRightHandWeapon.PlayActionByName(_GenWeaponActionName(szAct, m_iGender), 1.0f, true, 200, true, iAction, bHideFX);
nTime1 = m_pPlayerModel.GetComActTimeSpanByName(szAct);
szAct = $"{action.data.action_prefix}_{szActionMiddleName}_{action.data.action_weapon_suffix[weapon_type].suffix}Âä";
QueueNonSkillActionWithName(iAction, szAct, 0, false, bHideFX);
if (pRightHandWeapon != null && IsUsingMagicWeapon())
pRightHandWeapon.QueueAction(_GenWeaponActionName(szAct, m_iGender), 0, iAction, false, false, bHideFX);
nTime2 = m_pPlayerModel.GetComActTimeSpanByName(szAct);*/
}
// ==============================
// Kết thúc bằng FightStand
// ==============================
PLAYER_ACTION stand_action = m_PlayerActions[(int)PLAYER_ACTION_TYPE.ACT_FIGHTSTAND];
szAct = EC_Utility.BuildActionName(stand_action, 0);
EventBus.PublishChannel(m_PlayerInfo.cid, new QueueActionEvent(szAct));
/* QueueNonSkillActionWithName(ACT_FIGHTSTAND, szAct, 300, false, bHideFX, true);
if (pRightHandWeapon != null && IsUsingMagicWeapon())
pRightHandWeapon.QueueAction(_GenWeaponActionName(szAct, m_iGender), 300, iAction, false, false, bHideFX, true);*/
// ==============================
// Điều chỉnh tốc độ phát animation theo tốc độ tấn công
// ==============================
/* if (nAttackSpeed > 0)
{
float vScale = (nTime1 + nTime2) / (float)nAttackSpeed;
if (vScale > 0f)
{
m_pPlayerModel.SetPlaySpeed(vScale);
if (pRightHandWeapon != null && IsUsingMagicWeapon())
pRightHandWeapon.SetPlaySpeed(vScale);
}
}
attackTime = nTime1 + nTime2;*/
// ==============================
// Cập nhật vị trí weapon hanger (vũ khí)
// ==============================
//UpdateWeaponHangerPosByAction(iAction);
return true;
}
public bool m_bShowWeapon;
public void ShowWeaponByConfig(PLAYER_ACTION_INFO_CONFIG p)
{
m_bShowWeapon = p.hide_weapon != 0 ? false : true;
//ShowWeapon(m_bShowWeapon);
}
public int GetShowingWeaponType()
{
int weapon_type = 0;
if (CanShowFashionWeapon((int)m_uAttackType, m_iFashionWeaponType) && m_aEquips[(int)IndexOfIteminEquipmentInventory.EQUIPIVTR_FASHION_WEAPON] != 0)
{
weapon_type = (m_iFashionWeaponType == DEFAULT_ACTION_TYPE || !IsWeaponAttached()) ?
10 : m_iFashionWeaponType;
}
else
{
weapon_type = (m_uAttackType == DEFAULT_ACTION_TYPE || !IsWeaponAttached()) ?
10 : (int)m_uAttackType;
}
return weapon_type;
}
public bool IsWeaponAttached()
{
return m_bWeaponAttached;
}
public bool InFashionMode() { return m_bFashionMode; }
public bool CanShowFashionWeapon(int weapon_type, int fashion_weapon_type)
{
return IsFashionWeaponTypeFit(weapon_type, fashion_weapon_type) && InFashionMode();
}
public bool IsFashionWeaponTypeFit(int weapon_type, int fashion_weapon_type)
{
if (fashion_weapon_type < 0 || fashion_weapon_type >= NUM_WEAPON_TYPE) return false;
FASHION_WEAPON_CONFIG? pConfig = GetFashionConfig();
if (null == pConfig)
{
BMLogger.LogError("CECPlayer::GetFashionConfig, Failed to load fashion weapon config");
return false;
}
int fashion_weapon_mask = (int)pConfig.Value.action_mask[fashion_weapon_type];
return (fashion_weapon_mask & (1 << GetWeaponType(weapon_type))) != 0;
}
public FASHION_WEAPON_CONFIG GetFashionConfig()
{
FASHION_WEAPON_CONFIG? pFashionConfig = null;
if (null == pFashionConfig)
{
elementdataman pDataMan = ElementDataManProvider.GetElementDataMan();
DATA_TYPE DataType = DATA_TYPE.DT_FASHION_WEAPON_CONFIG;
uint tid = pDataMan.get_id_with_data_type(ID_SPACE.ID_SPACE_CONFIG, DataType);
if (tid != 0)
{
pFashionConfig = (FASHION_WEAPON_CONFIG)pDataMan.get_data_ptr(tid, ID_SPACE.ID_SPACE_CONFIG, ref DataType);
BMLogger.LogError($"HoangDev : get_data_ptr {pFashionConfig.GetType()}");
}
}
return pFashionConfig.Value;
}
public float GetTouchRadius() { return m_fTouchRad; }
// Is player in battle
public bool IsInBattle() { return m_iBattleCamp != Player_camp_in_battle.GP_BATTLE_CAMP_NONE; }
@@ -383,6 +699,8 @@ public abstract class EC_Player : CECObject
return true;
}
public const uint DEFAULT_ACTION_TYPE = 0xFFFFFFFF;
public static int GetWeaponType(int iWeaponType) { return iWeaponType == DEFAULT_ACTION_TYPE ? 10 : iWeaponType; }
public bool IsInFactionPVP() => (m_factionPVPMask & 0x01) != 0;
public bool CanAttackFactionPVPMineCar() => (m_factionPVPMask & 0x02) != 0;
public bool CanAttackFactionPVPMineBase() => (m_factionPVPMask & 0x04) != 0;
@@ -462,9 +780,11 @@ public abstract class EC_Player : CECObject
}
// Get move environment
public int GetMoveEnv(){ return m_iMoveEnv; }
public int GetMoveEnv() { return m_iMoveEnv; }
public bool IsShapeChanged() { return m_iShape != 0; }
public int GetWeaponID() { return m_aEquips[(int)IndexOfIteminEquipmentInventory.EQUIPIVTR_WEAPON] & 0xffff; }
public bool IsAllResReady() { return (m_dwResFlags & (uint)PlayerResourcesReadyFlag.RESFG_ALL) == (uint)PlayerResourcesReadyFlag.RESFG_ALL; }
// Get character ID
public int GetCharacterID(){ return m_PlayerInfo.cid; }
}
public struct PlayActionEvent
{
@@ -474,6 +794,15 @@ public struct PlayActionEvent
this.AnimationName = animationName;
}
}
public struct QueueActionEvent
{
public string AnimationName;
public QueueActionEvent(string animationName)
{
this.AnimationName = animationName;
}
}
[Serializable]
public struct INFO
{
@@ -487,7 +816,15 @@ public struct INFO
this.crc_e = crc_;
}
}
public enum PlayerResourcesReadyFlag
{
RESFG_SKELETON = 0x01,
RESFG_SKIN = 0x02,
RESFG_CUSTOM = 0x04,
RESFG_ASSEMBLED = 0x08,
RESFG_ALL = 0x0f,
};
public static class Duel_state // Duel state
{
public const int DUEL_ST_NONE = 0,
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 041192bec8f11c747a80df312c2df184
+57
View File
@@ -264,6 +264,63 @@ public class CECNPC : CECObject
}
}
}
public void Damaged(int iDamage, uint dwModifier/* 0 */)
{
if (iDamage == -1 || iDamage == -2)
{
// when else player hit this npc iDamage is -1,
// so if iDamage is -1 we will shoud the wounded animation
if (iDamage == -1)
PlayModelAction((int)NPCActionIndex. ACT_WOUNDED);
DamageTextManager.Instance.SpawnDamage(transform.position, iDamage, Color.red, 1.0f);
/*if ((dwModifier & (uint)MOD.MOD_IMMUNE) != 0 *//* && !IsImmuneDisable()*//*)
textma
else if (dwModifier & CECAttackEvent::MOD_NULLITY)
BubbleText(BUBBLE_INVALIDHIT, 0);
else if (dwModifier & CECAttackEvent::MOD_ENCHANT_FAILED)
BubbleText(BUBBLE_LOSE, 0);
else if (dwModifier & CECAttackEvent::MOD_SUCCESS)
BubbleText(BUBBLE_SUCCESS, 0);
else if (dwModifier & CECAttackEvent::MOD_DODGE_DEBUFF)
BubbleText(BUBBLE_DODGE_DEBUFF, 0);*/
}
else
{
// this message is related to the host, so we should show a pop up message
// Popup a damage decal
/* bool bDeadlyStrike = (dwModifier & CECAttackEvent::MOD_CRITICAL_STRIKE) ? true : false;
bool bRetort = (dwModifier & CECAttackEvent::MOD_RETORT) ? true : false;*/
if (iDamage > 0)
{
PlayModelAction((int)NPCActionIndex.ACT_WOUNDED);
DamageTextManager.Instance.SpawnDamage(transform.position, iDamage, Color.red, 1.0f);
/* int p1 = 0;
if (bDeadlyStrike)
p1 |= 0x0001;
else if (bRetort)
p1 |= 0x0002;*/
/* if (dwModifier & CECAttackEvent::MOD_REBOUND)
BubbleText(BUBBLE_REBOUND, (DWORD)iDamage);
else if (dwModifier & CECAttackEvent::MOD_BEAT_BACK)
BubbleText(BUBBLE_BEAT_BACK, (DWORD)iDamage);
else
BubbleText(BUBBLE_DAMAGE, (DWORD)iDamage, p1);*/
}
/* else if ((dwModifier & CECAttackEvent::MOD_IMMUNE) && !IsImmuneDisable())
BubbleText(BUBBLE_IMMUNE, 0);
else if (dwModifier & CECAttackEvent::MOD_NULLITY)
BubbleText(BUBBLE_INVALIDHIT, 0);
else if (dwModifier & CECAttackEvent::MOD_ENCHANT_FAILED)
BubbleText(BUBBLE_LOSE, 0);
else if (dwModifier & CECAttackEvent::MOD_SUCCESS)
BubbleText(BUBBLE_SUCCESS, 0);
else
BubbleText(BUBBLE_HITMISSED, 0);*/
}
}
public void WorkFinished(int iWorkID)
{
+3 -1
View File
@@ -1,4 +1,5 @@
using Animancer;
using BrewMonster;
using UnityEngine;
public class NPCVisual : MonoBehaviour
@@ -6,10 +7,11 @@ public class NPCVisual : MonoBehaviour
[SerializeField] NamedAnimancerComponent namedAnimancer;
public bool TryPlayAction(string animationName)
{
BMLogger.LogError("HoangDev: TryPlayAction: " + animationName);
if (namedAnimancer == null) return false;
if (namedAnimancer.IsPlaying(animationName)) return false;
return namedAnimancer.TryPlay("慢速移动") == null;
return namedAnimancer.TryPlay(animationName) == null;
}
public void InitNPCEventDoneHandler()
{
@@ -846,6 +846,15 @@ namespace CSNetwork.GPDataType
public byte[] content;
};
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct cmd_host_attack_result
{
public int idTarget;
public int iDamage; // Èç¹ûÊÇ0±íʾûÓл÷ÖÐ
public int attack_flag; // ±ê¼Ç¸Ã¹¥»÷ÊÇ·ñÓй¥»÷ÓÅ»¯·ûºÍ·ÀÓùÓÅ»¯·ûºÍÖØ»÷·¢Éú
public byte attack_speed;
};
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct cmd_own_ivtr_detail_info
{
@@ -319,7 +319,7 @@ namespace CSNetwork
}
var pCmdHeader = BitConverter.ToUInt16(byteArrHeader);
//sss
_logger.Info($"### GameDataSend: CMDID {pCmdHeader}");
BMLogger.LogError($"### GameDataSend: CMDID {pCmdHeader}");
int iHostID = _selectedRole.roleid;
switch (pCmdHeader)
{
@@ -339,7 +339,6 @@ namespace CSNetwork
case CommandID.PLAYER_INFO_00:
case CommandID.SELF_INFO_1:
// OnMsgPlayerInfo(-1, pDataBuf, pCmdHeader);
_logger.Info($"HoangDev : EC_MsgDef.MSG_PM_PLAYERINFO");
EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PLAYERINFO, (int)MANAGER_INDEX.MAN_PLAYER, -1, pDataBuf, pCmdHeader, iHostID, _selectedRole);
break;
case CommandID.OBJECT_MOVE:
@@ -352,7 +351,6 @@ namespace CSNetwork
}
else if (ISNPCID(idObjMove))
{
_logger.Info("HoangDev : NPC OBJECT_MOVE");
EC_ManMessage.PostMessage(EC_MsgDef.MSG_NM_NPCMOVE, (int)MANAGER_INDEX.MAN_NPC, 0, pDataBuf, pCmdHeader);
}
break;
@@ -365,7 +363,6 @@ namespace CSNetwork
}
else if (ISNPCID(id1))
{
_logger.Info("HoangDev : NPC OBJECT_MOVE");
EC_ManMessage.PostMessage(EC_MsgDef.MSG_NM_NPCSTOPMOVE, (int)MANAGER_INDEX.MAN_NPC, 0, pDataBuf, pCmdHeader);
}
break;
@@ -374,7 +371,6 @@ namespace CSNetwork
case CommandID.OWN_IVTR_DETAIL_DATA:
case CommandID.GET_OWN_MONEY:
case CommandID.CHANGE_IVTR_SIZE:
_logger.Info($"HUNG INVENTORY2");
EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_IVTRINFO, (int)MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader, iHostID);
break;
case CommandID.EXG_IVTR_ITEM:
@@ -385,7 +381,6 @@ namespace CSNetwork
case CommandID.MOVE_EQUIP_ITEM:
case CommandID.UNFREEZE_IVTR_SLOT:
case CommandID.PLAYER_EQUIP_TRASHBOX_ITEM:
_logger.Info($"HUNG EQUIP ITEM: " + pCmdHeader);
EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_ITEMOPERATION, (int)MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader);
break;
case CommandID.MATTER_INFO_LIST:
@@ -398,7 +393,6 @@ namespace CSNetwork
EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_PICKUPITEM, (int)MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader);
break;
case CommandID.HOST_CORRECT_POS:
_logger.Info($"HoangDev HOST_CORRECT_POSHOST_CORRECT_POSHOST_CORRECT_POS");
EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_CORRECTPOS, (int)MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader, iHostID);
break;
case CommandID.OWN_ITEM_INFO:
@@ -409,7 +403,6 @@ namespace CSNetwork
case CommandID.NPC_INFO_00:
case CommandID.NPC_ENTER_WORLD:
case CommandID.NPC_VISIBLE_TID_NOTIFY:
_logger.Info($"HoangDev :NPC_VISIBLE_TID_NOTIFY");
EC_ManMessage.PostMessage(EC_MsgDef.MSG_NM_NPCINFO, (int)MANAGER_INDEX.MAN_NPC, 0, pDataBuf, pCmdHeader, dwDataSize);
break;
case CommandID.TASK_DATA:
@@ -429,12 +422,10 @@ namespace CSNetwork
EC_ManMessage.PostMessage(EC_MsgDef.MSG_NM_NPCATKRESULT, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader);
break;
case CommandID.HOST_ATTACKRESULT:
BMLogger.LogError("HoangDev : HOST_ATTACKRESULT");
EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_ATKRESULT, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader);
break;
case CommandID.HOST_ATTACKED:
BMLogger.LogError("HoangDev : HOST_ATTACKED");
EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_ATKRESULT, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader);
EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_ATTACKED, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader);
break;
case CommandID.ERROR_MESSAGE:
@@ -74,8 +74,8 @@ namespace BrewMonster
if (!(pObject = EC_ManPlayer.GetPlayer(idObject)))
return null;
if ((iAliveFlag == 1 && (pObject as EC_Player).IsDead()) ||
(iAliveFlag == 2 && !(pObject as EC_Player).IsDead()))
if ((iAliveFlag == 1 && (pObject as CECPlayer).IsDead()) ||
(iAliveFlag == 2 && !(pObject as CECPlayer).IsDead()))
return null;
}
//else if (GPDataTypeHelper.ISMATTERID(idObject))
@@ -1,5 +1,5 @@
using UnityEngine;
using static EC_Player;
using static CECPlayer;
public class PlayerIdleState : PlayerState
{
@@ -1,5 +1,5 @@
using UnityEngine;
using static EC_Player;
using static CECPlayer;
public class PlayerMoveState : PlayerState
{
@@ -7,7 +7,7 @@ using UnityEngine;
namespace PerfectWorld.Scripts.Player
{
public class EC_ElsePlayer : EC_Player
public class EC_ElsePlayer : CECPlayer
{
A3DVECTOR3 m_vMoveDir; // Player's velocity
A3DVECTOR3 m_vServerPos; // Player's real position on server
@@ -52,6 +52,12 @@ namespace BrewMonster.UI
_usernameInputField.text = "test004";
_passwordInputField.text = "123456";
}
if (Input.GetKeyUp(KeyCode.Tab))
{
_usernameInputField.text = "test005";
_passwordInputField.text = "123456";
OnLoginButtonClicked();
}
#endif
}
+201 -1
View File
@@ -812,6 +812,11 @@ MonoBehaviour:
- {fileID: 7400000, guid: 29895f3687b86a24ba1bff2318b1d817, type: 2}
- {fileID: 7400000, guid: 9b5c3773d9888954c95132e25788ae54, type: 2}
- {fileID: 7400000, guid: 5f21aa4feb9cf1e49b63d5e7b7d9ad58, type: 2}
- {fileID: 7400000, guid: 4c93f18fe5082524d8ccda024f7988ad, type: 2}
- {fileID: 7400000, guid: bc909de03ae7dcc4d824253bf652de1d, type: 2}
- {fileID: 7400000, guid: 211cf985d64485e4ca42f7d8d6509e87, type: 2}
- {fileID: 7400000, guid: caa9485da71a78b4da087ae69bf7120d, type: 2}
- {fileID: 7400000, guid: 233ca05b3510f614e8b2ea31731dc298, type: 2}
--- !u!21 &19752687
Material:
serializedVersion: 8
@@ -75381,6 +75386,182 @@ Mesh:
offset: 0
size: 0
path:
--- !u!1 &927529342
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 927529343}
- component: {fileID: 927529345}
- component: {fileID: 927529344}
m_Layer: 0
m_Name: DamageText
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &927529343
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 927529342}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 1336646766}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: 0, y: 9000}
m_SizeDelta: {x: 20, y: 5}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &927529344
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 927529342}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 9541d86e2fd84c1d9990edf0852d74ab, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_text:
m_isRightToLeft: 0
m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
m_fontSharedMaterials: []
m_fontMaterial: {fileID: 0}
m_fontMaterials: []
m_fontColor32:
serializedVersion: 2
rgba: 4294967295
m_fontColor: {r: 1, g: 1, b: 1, a: 1}
m_enableVertexGradient: 0
m_colorMode: 3
m_fontColorGradient:
topLeft: {r: 1, g: 1, b: 1, a: 1}
topRight: {r: 1, g: 1, b: 1, a: 1}
bottomLeft: {r: 1, g: 1, b: 1, a: 1}
bottomRight: {r: 1, g: 1, b: 1, a: 1}
m_fontColorGradientPreset: {fileID: 0}
m_spriteAsset: {fileID: 0}
m_tintAllSprites: 0
m_StyleSheet: {fileID: 0}
m_TextStyleHashCode: -1183493901
m_overrideHtmlColors: 0
m_faceColor:
serializedVersion: 2
rgba: 4294967295
m_fontSize: 2
m_fontSizeBase: 2
m_fontWeight: 400
m_enableAutoSizing: 0
m_fontSizeMin: 18
m_fontSizeMax: 72
m_fontStyle: 0
m_HorizontalAlignment: 2
m_VerticalAlignment: 512
m_textAlignment: 65535
m_characterSpacing: 0
m_wordSpacing: 0
m_lineSpacing: 0
m_lineSpacingMax: 0
m_paragraphSpacing: 0
m_charWidthMaxAdj: 0
m_TextWrappingMode: 0
m_wordWrappingRatios: 0.4
m_overflowMode: 0
m_linkedTextComponent: {fileID: 0}
parentLinkedComponent: {fileID: 0}
m_enableKerning: 0
m_ActiveFontFeatures: 6e72656b
m_enableExtraPadding: 0
checkPaddingRequired: 0
m_isRichText: 1
m_EmojiFallbackSupport: 1
m_parseCtrlCharacters: 1
m_isOrthographic: 0
m_isCullingEnabled: 0
m_horizontalMapping: 0
m_verticalMapping: 0
m_uvLineOffset: 0
m_geometrySortingOrder: 0
m_IsTextObjectScaleStatic: 0
m_VertexBufferAutoSizeReduction: 0
m_useMaxVisibleDescender: 1
m_pageToDisplay: 1
m_margin: {x: 0, y: 0, z: 0, w: 0}
m_isUsingLegacyAnimationComponent: 0
m_isVolumetricText: 0
_SortingLayer: 0
_SortingLayerID: 0
_SortingOrder: 0
m_hasFontAssetChanged: 0
m_renderer: {fileID: 927529345}
m_maskType: 0
--- !u!23 &927529345
MeshRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 927529342}
m_Enabled: 1
m_CastShadows: 0
m_ReceiveShadows: 0
m_DynamicOccludee: 1
m_StaticShadowCaster: 0
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_RayTracingMode: 2
m_RayTraceProcedural: 0
m_RayTracingAccelStructBuildFlagsOverride: 0
m_RayTracingAccelStructBuildFlags: 1
m_SmallMeshCulling: 1
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_ReceiveGI: 1
m_PreserveUVs: 0
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_StitchLightmapSeams: 1
m_SelectedEditorRenderState: 3
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
m_AdditionalVertexStreams: {fileID: 0}
--- !u!1 &928368405
GameObject:
m_ObjectHideFlags: 0
@@ -104206,6 +104387,7 @@ GameObject:
m_Component:
- component: {fileID: 1336646766}
- component: {fileID: 1336646767}
- component: {fileID: 1336646768}
m_Layer: 0
m_Name: NPC Manager
m_TagString: Untagged
@@ -104225,7 +104407,8 @@ Transform:
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Children:
- {fileID: 927529343}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &1336646767
@@ -104241,6 +104424,23 @@ MonoBehaviour:
m_Name:
m_EditorClassIdentifier:
modelPlayerCharacter: {fileID: 960760103}
--- !u!114 &1336646768
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1336646764}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: e7981b037b60f4a4989ff59265a308ad, type: 3}
m_Name:
m_EditorClassIdentifier:
damageTextPrefab: {fileID: 927529344}
poolSize: 20
offset: {x: 0, y: 2, z: 0}
riseDistance: 1.5
riseDuration: 0.8
--- !u!1 &1338403792
GameObject:
m_ObjectHideFlags: 0
+151 -96
View File
@@ -1,6 +1,7 @@
using BrewMonster;
using BrewMonster.Network;
using CSNetwork;
using CSNetwork.Common;
using CSNetwork.GPDataType;
using CSNetwork.Protocols;
using CSNetwork.Protocols.RPCData;
@@ -12,13 +13,14 @@ using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using TMPro;
using UnityEditor.Experimental.GraphView;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using Scene = UnityEngine.SceneManagement.Scene;
public class CECHostPlayer : EC_Player
public class CECHostPlayer : CECPlayer
{
[SerializeField] private TextMeshPro txtName;
[SerializeField] private CharacterController controller;
@@ -92,12 +94,12 @@ public class CECHostPlayer : EC_Player
public void SetModelHostPlayer()
{
m_pPlayerModel = NPCManager.Instance.GetModelPlayer();
_pPlayerModel = NPCManager.Instance.GetModelPlayer();
Scene scene = SceneManager.GetSceneByName("WorldRender");
SceneManager.MoveGameObjectToScene(m_pPlayerModel, scene);
m_pPlayerModel.transform.SetParent(parentModel);
m_pPlayerModel.transform.localPosition = Vector3.zero;
m_pPlayerModel.SetActive(true);
SceneManager.MoveGameObjectToScene(_pPlayerModel, scene);
_pPlayerModel.transform.SetParent(parentModel);
_pPlayerModel.transform.localPosition = Vector3.zero;
_pPlayerModel.SetActive(true);
}
private void Start()
{
@@ -133,20 +135,20 @@ public class CECHostPlayer : EC_Player
{
CECObject clickedObject = hit.collider.gameObject.GetComponent<CECObject>();
if(clickedObject != null)
if (clickedObject != null)
{
int idObject = CECObject.GetObjectID(clickedObject);
if (idObject != 0)
{
CECNPC pNPC = EC_ManMessageMono.Instance._CECNPCMan.GetNPC(idObject);
if(pNPC != null)
if (pNPC != null)
{
if (!pNPC.IsDead()/* && m_idSelTarget == idObject*/)
{
idTraceTarget = idObject;
idSelTarget = idObject;
}
if (idTraceTarget != 0)
if (idTraceTarget != 0)
{
if (AttackableJudge(idObject, bForceAttack) == 1)
iTraceReason = CECHPWorkTrace.Trace_reason.TRACE_ATTACK;
@@ -339,11 +341,61 @@ public class CECHostPlayer : EC_Player
case int value when value == EC_MsgDef.MSG_HST_PICKUPITEM:
OnMsgHstPickupItem(Msg);
break;
case int value when value == EC_MsgDef.MSG_HST_SELTARGET:
case int value when value == EC_MsgDef.MSG_HST_SELTARGET:
OnMsgHstSelTarget(Msg); break;
case int value when value == EC_MsgDef.MSG_HST_ATKRESULT: OnMsgHstAttackResult(Msg); break;
//case int value when value == EC_MsgDef.MSG_HST_ATTACKED: OnMsgHstAttacked(Msg); break;
case int value when value == EC_MsgDef.MSG_HST_HURTRESULT: OnMsgHstHurtResult(Msg); break;
}
}
public void OnMsgHstAttackResult(ECMSG Msg)
{
BMLogger.LogError($"dwParam1 type = {Msg.dwParam1?.GetType()}");
byte[] data = Msg.dwParam1 as byte[];
cmd_host_attack_result pCmd = EC_Utility.ByteArrayToStructure<cmd_host_attack_result>(data);
int iAttackTime = 0;
PlayAttackEffect(pCmd.idTarget, 0, 0, pCmd.iDamage, (uint)pCmd.attack_flag, pCmd.attack_speed * 50, ref iAttackTime);
TurnFaceTo(pCmd.idTarget);
if (iAttackTime != 0)
{
if (m_pWorkMan.GetRunningWork(CECHPWork.Host_work_ID.WORK_HACKOBJECT) is CECHPWorkMelee pCurWork)
{
pCurWork.SetIdleTime(iAttackTime);
}
}
}
private void OnMsgHstHurtResult(ECMSG Msg)
{
/* BMLogger.LogError("HoangDev : OnMsgHstHurtResult");
int cmd = Convert.ToInt32(Msg.dwParam2);
if (cmd == CommandID.BE_HURT)
{
cmd_be_hurt pCmd = (cmd_be_hurt)Msg.dwParam1;
if (pCmd.damage != 0)
Damaged(pCmd->damage);
}
else if (cmd == CommandID.HURT_RESULT)
{
cmd_hurt_result pCmd = (cmd_hurt_result)Msg.dwParam1;
if (pCmd.target_id == m_PlayerInfo.cid)
return; // Host himself will receive BE_HURT, so ignore this.
if (UnityGameSession.Instance.GameSession.ISPLAYERID(pCmd.target_id))
{
CECElsePlayer pTarget = m_pPlayerMan.GetElsePlayer(pCmd.target_id);
if (pTarget)
pTarget->Damaged(pCmd->damage);
}
else if (UnityGameSession.Instance.GameSession.ISNPCID(pCmd.target_id))
{
CECNPC pTarget = EC_ManMessageMono.Instance._CECNPCMan.GetNPC(pCmd.target_id);
if (pTarget)
pTarget.Damaged(pCmd.damage);
}
}*/
}
public void OnMsgHstPickupItem(in ECMSG Msg)
{
var data = Msg.dwParam1 as byte[];
@@ -351,85 +403,44 @@ public class CECHostPlayer : EC_Player
switch (cmd)
{
case CommandID.PICKUP_ITEM:
{
// Parse the pickup item data from the server response
if (data != null && data.Length >= 16)
{
int tid = BitConverter.ToInt32(data, 0);
int expire_date = BitConverter.ToInt32(data, 4);
uint iAmount = BitConverter.ToUInt32(data, 8);
uint iSlotAmount = BitConverter.ToUInt32(data, 12);
byte byPackage = data[16];
byte bySlot = data[17];
Debug.Log($"[Inventory] PICKUP_ITEM: tid={tid}, expire_date={expire_date}, iAmount={iAmount}, iSlotAmount={iSlotAmount}, byPackage={byPackage}, bySlot={bySlot}");
// Notify pickupItem script about successful pickup
pickupItem pickupScript = UnityEngine.Object.FindFirstObjectByType<pickupItem>();
if (pickupScript != null)
// Parse the pickup item data from the server response
if (data != null && data.Length >= 16)
{
pickupScript.OnPickupSuccess(tid);
}
// Create new inventory item data
var newItem = new InventoryItemData
{
Package = byPackage,
Slot = bySlot,
TemplateId = tid,
ExpireDate = expire_date,
State = 0,
Count = (int)iAmount,
Crc = 0,
Content = null
};
// Add item to inventory
EC_Inventory.SetItem(byPackage, bySlot, newItem);
Debug.Log($"[Inventory] Successfully added item {tid} to package {byPackage}, slot {bySlot} with count {iAmount}");
// Trigger UI refresh if an EC_InventoryUI is present in scene
var ui = GameObject.FindFirstObjectByType<EC_InventoryUI>();
if (ui != null)
{
ui.RefreshAll();
}
}
else
{
Debug.LogWarning("[Inventory] PICKUP_ITEM: Invalid data length");
}
break;
}
}
}
public void OnMsgHstItemOperation(ECMSG Msg)
{
var data = Msg.dwParam1 as byte[];
int cmd = Convert.ToInt32(Msg.dwParam2);
switch (cmd)
{
case CommandID.PLAYER_DROP_ITEM:
{
// Parse the drop item data from the server response
if (data != null && data.Length >= 6)
{
byte byPackage = data[0];
byte bySlot = data[1];
int count = BitConverter.ToInt32(data, 2);
int tid = BitConverter.ToInt32(data, 6);
byte reason = data[10];
Debug.Log($"[Inventory] PLAYER_DROP_ITEM: package={byPackage}, slot={bySlot}, count={count}, tid={tid}, reason={reason}");
// Update the inventory by removing the item
bool success = EC_Inventory.RemoveItem(byPackage, bySlot, count);
if (success)
{
Debug.Log($"[Inventory] Successfully removed {count} items from package {byPackage}, slot {bySlot}");
int tid = BitConverter.ToInt32(data, 0);
int expire_date = BitConverter.ToInt32(data, 4);
uint iAmount = BitConverter.ToUInt32(data, 8);
uint iSlotAmount = BitConverter.ToUInt32(data, 12);
byte byPackage = data[16];
byte bySlot = data[17];
Debug.Log($"[Inventory] PICKUP_ITEM: tid={tid}, expire_date={expire_date}, iAmount={iAmount}, iSlotAmount={iSlotAmount}, byPackage={byPackage}, bySlot={bySlot}");
// Notify pickupItem script about successful pickup
pickupItem pickupScript = UnityEngine.Object.FindFirstObjectByType<pickupItem>();
if (pickupScript != null)
{
pickupScript.OnPickupSuccess(tid);
}
// Create new inventory item data
var newItem = new InventoryItemData
{
Package = byPackage,
Slot = bySlot,
TemplateId = tid,
ExpireDate = expire_date,
State = 0,
Count = (int)iAmount,
Crc = 0,
Content = null
};
// Add item to inventory
EC_Inventory.SetItem(byPackage, bySlot, newItem);
Debug.Log($"[Inventory] Successfully added item {tid} to package {byPackage}, slot {bySlot} with count {iAmount}");
// Trigger UI refresh if an EC_InventoryUI is present in scene
var ui = GameObject.FindFirstObjectByType<EC_InventoryUI>();
if (ui != null)
@@ -439,15 +450,56 @@ public class CECHostPlayer : EC_Player
}
else
{
Debug.LogWarning($"[Inventory] Failed to remove items from package {byPackage}, slot {bySlot}");
Debug.LogWarning("[Inventory] PICKUP_ITEM: Invalid data length");
}
break;
}
else
}
}
public void OnMsgHstItemOperation(ECMSG Msg)
{
var data = Msg.dwParam1 as byte[];
int cmd = Convert.ToInt32(Msg.dwParam2);
switch (cmd)
{
case CommandID.PLAYER_DROP_ITEM:
{
Debug.LogWarning("[Inventory] PLAYER_DROP_ITEM: Invalid data length");
// Parse the drop item data from the server response
if (data != null && data.Length >= 6)
{
byte byPackage = data[0];
byte bySlot = data[1];
int count = BitConverter.ToInt32(data, 2);
int tid = BitConverter.ToInt32(data, 6);
byte reason = data[10];
Debug.Log($"[Inventory] PLAYER_DROP_ITEM: package={byPackage}, slot={bySlot}, count={count}, tid={tid}, reason={reason}");
// Update the inventory by removing the item
bool success = EC_Inventory.RemoveItem(byPackage, bySlot, count);
if (success)
{
Debug.Log($"[Inventory] Successfully removed {count} items from package {byPackage}, slot {bySlot}");
// Trigger UI refresh if an EC_InventoryUI is present in scene
var ui = GameObject.FindFirstObjectByType<EC_InventoryUI>();
if (ui != null)
{
ui.RefreshAll();
}
}
else
{
Debug.LogWarning($"[Inventory] Failed to remove items from package {byPackage}, slot {bySlot}");
}
}
else
{
Debug.LogWarning("[Inventory] PLAYER_DROP_ITEM: Invalid data length");
}
break;
}
break;
}
case CommandID.EQUIP_ITEM:
{
byte index_inv = data[0];
@@ -592,6 +644,7 @@ public class CECHostPlayer : EC_Player
if (txtName != null) txtName.text = roleName;
transform.position = pos;
SetModelHostPlayer();
m_dwResFlags = (uint)PlayerResourcesReadyFlag.RESFG_ALL;
Debug.LogError("Pos Character = " + pos);
joystick = FindAnyObjectByType<Joystick>();
EventBus.Subscribe<JoystickRealeaseEvent>(JoystickRelease);
@@ -932,7 +985,7 @@ public class CECHostPlayer : EC_Player
return Mathf.Sqrt(v.x * v.x + v.y * v.y + v.z * v.z);
}
public int GetCharacterID(){ return m_PlayerInfo.cid; }
public int GetCharacterID() { return m_PlayerInfo.cid; }
public bool CannotAttack() { return (m_dwLIES & (uint)Logic_Influence_Extned_states.LIES_DISABLEFIGHT) != 0; }
@@ -1001,17 +1054,19 @@ public class CECHostPlayer : EC_Player
A3DVECTOR3 vector = new A3DVECTOR3(gameObject.transform.position.x, gameObject.transform.position.y, gameObject.transform.position.z);
return CanTouchTarget(vector, vTargetPos, fTargetRad, iReason, fMaxCut);
}
public bool IsRooting() {
public bool IsRooting()
{
var mask = (uint)(Logic_Influence_Extned_states.LIES_ROOT
| Logic_Influence_Extned_states.LIES_SLEEP
| Logic_Influence_Extned_states.LIES_STUN);
return (m_dwLIES & mask) != 0; }
return (m_dwLIES & mask) != 0;
}
bool IsInFortress() { return m_fortressEnter.role_in_war != 0; }
bool IsPVPOpen() { return m_pvp.bEnable; }
// Get faction ID
int GetFactionID(){ return m_idFaction; }
int GetFactionID() { return m_idFaction; }
public bool IsJumping() { return m_iJumpCount > 0; }
+25 -8
View File
@@ -3,8 +3,9 @@ using CSNetwork.GPDataType;
using System;
using System.Collections;
using System.Runtime.InteropServices;
using System.Text;
using UnityEngine;
using static EC_Player;
using static CECPlayer;
public static class EC_Utility
{
@@ -32,16 +33,21 @@ public static class EC_Utility
}
}
public static float FIX8TOFLOAT(int x) => x / 256.0f;
public static T ByteArrayToStructure<T>(byte[] bytes) where T : struct
public static T ByteArrayToStructure<T>(byte[] data) where T : struct
{
GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
int size = Marshal.SizeOf(typeof(T));
if (data.Length < size)
throw new ArgumentException($"Data length {data.Length} < struct size {size}");
IntPtr ptr = Marshal.AllocHGlobal(size);
try
{
return Marshal.PtrToStructure<T>(handle.AddrOfPinnedObject());
Marshal.Copy(data, 0, ptr, size);
return Marshal.PtrToStructure<T>(ptr);
}
finally
{
handle.Free();
Marshal.FreeHGlobal(ptr);
}
}
public static Vector3 glb_DecompressDirH(byte byDir)
@@ -72,7 +78,18 @@ public static class EC_Utility
{
return Mathf.Sqrt(v.x * v.x + v.z * v.z);
}
public static string BuildActionName(PLAYER_ACTION action, int weaponType)
public static string FixGBKString(string input)
{
// Giả sử input hiện đang là "Æð"
// B1: lấy bytes theo "Latin1" (mỗi ký tự 1 byte giữ nguyên giá trị gốc)
byte[] bytes = Encoding.GetEncoding("ISO-8859-1").GetBytes(input);
// B2: giải mã lại bằng GBK (Code page 936)
string decoded = Encoding.GetEncoding(936).GetString(bytes);
return decoded;
}
public static string BuildActionName(PLAYER_ACTION action, int weaponType, string tail = "")
{
string prefix = action.data.ActionPrefix ?? string.Empty;
string suffix = string.Empty;
@@ -83,8 +100,8 @@ public static class EC_Utility
{
suffix = action.data.action_weapon_suffix[weaponType].Suffix ?? string.Empty;
}
return $"{prefix}_{suffix}";
var tailFixed = FixGBKString(tail);
return $"{prefix}_{suffix}{tailFixed}";
}
// Build pvp mask
+1 -1
View File
@@ -54,7 +54,7 @@ public class GameController : MonoBehaviour
Debug.LogError("null prefab");
return;
}
EC_Player.InitStaticRes();
CECPlayer.InitStaticRes();
hostPlayer = Instantiate(characterPrefab, transform);
hostPlayer.InitCharacter(info);
cinemachineCamera.Follow = hostPlayer.transform;
+2 -2
View File
@@ -5,11 +5,11 @@ public class InitializePlayer /*: IAutoInitialize*/
{
public void Dispose()
{
EC_Player.Dispose();
CECPlayer.Dispose();
}
public void Initialize()
{
EC_Player.InitStaticRes();
CECPlayer.InitStaticRes();
}
}
-2
View File
@@ -1,2 +0,0 @@
fileFormatVersion: 2
guid: be4a22babee7846459b0421234a44c99
+49 -4
View File
@@ -1,5 +1,7 @@
using Animancer;
using Animancer;
using BrewMonster;
using System;
using System.Collections.Generic;
using UnityEngine;
public class PlayerVisual : MonoBehaviour
@@ -9,10 +11,16 @@ public class PlayerVisual : MonoBehaviour
[SerializeField] private INFO _playerInfo;
[SerializeField] private AnimancerState _currentState;
private readonly Queue<string> _animationQueue = new Queue<string>();
private void PlayActionEventHandler(PlayActionEvent @event)
{
BrewMonster.BMLogger.Log("PlayActionEventHandler : "+@event.AnimationName);
namedAnimancer.TryPlay(@event.AnimationName);
_currentState = namedAnimancer.TryPlay(@event.AnimationName);
if(_currentState == null)
{
BMLogger.LogError("HoangDev: PlayActionEventHandler Failed ");
}
}
public void InitHostPlayerEventDoneHandler()
@@ -23,7 +31,7 @@ public class PlayerVisual : MonoBehaviour
BrewMonster.BMLogger.LogError("animancer == null");
return;
}
var player = GetComponentInParent<EC_Player>();
var player = GetComponentInParent<CECPlayer>();
if(player == null)
{
BrewMonster.BMLogger.LogError("player == null");
@@ -31,7 +39,44 @@ public class PlayerVisual : MonoBehaviour
}
_playerInfo = player.GetPlayInfo();
EventBus.SubscribeChannel<PlayActionEvent>(_playerInfo.cid, PlayActionEventHandler);
EventBus.SubscribeChannel<QueueActionEvent>(_playerInfo.cid, QueueActionEventHandler);
}
private void QueueActionEventHandler(QueueActionEvent @event)
{
if(!EnqueueAnimation(@event.AnimationName))
{
BMLogger.LogError("HoangDev : EnqueueAnimation Failed");
}
}
public bool EnqueueAnimation(string animName)
{
if (namedAnimancer == null) return false;
_animationQueue.Enqueue(animName);
if (!namedAnimancer.IsPlaying())
PlayNext();
else
{
if (_currentState == null) return false;
_currentState.Events.OnEnd = PlayNext;
}
return true;
}
private void PlayNext()
{
if (_animationQueue.Count == 0)
{
return;
}
string animName = _animationQueue.Dequeue();
var state = namedAnimancer.TryPlay(animName);
// Khi clip kết thúc thì gọi tiếp cái kế tiếp
state.Events.OnEnd = PlayNext;
}
private void OnDestroy()
{
EventBus.UnsubscribeAllInChannel(_playerInfo.cid);