Merge pull request 'feature/skillBehavior' (#187) from feature/skillBehavior into develop

Reviewed-on: https://git.pthub.vn/Unity/perfect-world-unity/pulls/187
This commit is contained in:
hoangvd
2026-03-02 07:58:30 +00:00
18 changed files with 393 additions and 98 deletions
@@ -1,4 +1,6 @@
using BrewMonster.Network;
using System.Collections;
using EditorAttributes;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
@@ -18,6 +20,10 @@ namespace BrewMonster.Scripts
[Space(10)]
[Header("Command Buttons")]
[SerializeField] Button _btnNoCooldown;
[SerializeField] Button _btnToggleAutoWrath;
private bool _isAutoAddWrathEnabled = false;
private Coroutine _autoAddWrathCoroutine;
private void Awake()
{
@@ -25,8 +31,21 @@ namespace BrewMonster.Scripts
_btnOpen?.onClick.AddListener(OnBtnOpenClicked);
_btnClose?.onClick.AddListener(OnBtnCloseClicked);
_btnNoCooldown?.onClick.AddListener(OnBtnNoCooldownClicked);
}
_btnToggleAutoWrath?.onClick.AddListener(OnBtnToggleAutoWrathClicked);
DontDestroyOnLoad(this);
}
private void OnDestroy()
{
// Stop coroutine if running when object is destroyed
// 对象销毁时如果协程正在运行则停止它
if (_autoAddWrathCoroutine != null)
{
StopCoroutine(_autoAddWrathCoroutine);
_autoAddWrathCoroutine = null;
}
}
#region button events
private void OnBtnSendClicked()
@@ -57,6 +76,60 @@ namespace BrewMonster.Scripts
{
UnityGameSession.c2s_CmdDebug(8903, 73125);
}
private void OnBtnAddWrathClicked()
{
UnityGameSession.c2s_CmdDebug(1992);
}
//1992
#endregion
[ContextMenu("Toggle Auto-Add Wrath")]
public void OnBtnToggleAutoWrathClicked()
{
ToggleAutoAddWrath();
}
/// <summary>
/// Toggle auto-add wrath feature (calls OnBtnAddWrathClicked every 3 seconds)
/// 切换自动添加怒气功能(每3秒调用OnBtnAddWrathClicked
/// </summary>
public void ToggleAutoAddWrath()
{
_isAutoAddWrathEnabled = !_isAutoAddWrathEnabled;
if (_isAutoAddWrathEnabled)
{
// Start the coroutine if not already running
// 如果尚未运行,则启动协程
if (_autoAddWrathCoroutine == null)
{
_autoAddWrathCoroutine = StartCoroutine(AutoAddWrathCoroutine());
}
}
else
{
// Stop the coroutine if running
// 如果正在运行,则停止协程
if (_autoAddWrathCoroutine != null)
{
StopCoroutine(_autoAddWrathCoroutine);
_autoAddWrathCoroutine = null;
}
}
}
/// <summary>
/// Coroutine that calls OnBtnAddWrathClicked every 3 seconds
/// 每3秒调用OnBtnAddWrathClicked的协程
/// </summary>
private IEnumerator AutoAddWrathCoroutine()
{
while (_isAutoAddWrathEnabled)
{
OnBtnAddWrathClicked();
yield return new WaitForSeconds(3.0f);
}
_autoAddWrathCoroutine = null;
}
}
}
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 14a56e4ae79b92747a7e7d9361f3cbb7
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,14 @@
using UnityEngine;
using EditorAttributes;
namespace BrewMonster.Scripts
{
public class TestButtonAttribute : MonoBehaviour
{
[Button("Test Button")]
public void TestMethod()
{
Debug.Log("Test button clicked!");
}
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 1354ffe4a2a98bf4babd611fa7f66452
@@ -104,6 +104,10 @@ namespace BrewMonster
return bRet;
}
public virtual void Dispose() {
Instance = null;
}
public bool AddOneSkillGfxEvent(
A3DSkillGfxComposer pComposer,
long nHostID,
@@ -11,7 +11,7 @@ using System.Text;
using ModelRenderer.Scripts.Common;
using BrewMonster.Scripts;
using UnityEngine;
using Cysharp.Threading.Tasks;
using Cysharp.Threading.Tasks;
namespace BrewMonster
{
@@ -30,7 +30,7 @@ namespace BrewMonster
protected override void OnDestroy()
{
m_targets = null;
SkillGfxMan.InstanceSub = null;
SkillGfxMan.InstanceSub.Dispose();
base.OnDestroy();
}
private void Start()
@@ -52,7 +52,7 @@ namespace BrewMonster
LoadAllSkillGfxAsync();
}
/// <summary>
/// Load GFX for a specific skill on-demand (async, non-blocking)
/// Call this when a skill is about to be used for the first time
@@ -62,7 +62,7 @@ namespace BrewMonster
// Check if already loaded
if (m_pSkillGfxComposerMan.GetSkillGfxComposer((int)skillId) != null)
return; // Already loaded
// Get SkillStub instance / 获取技能存根实例
SkillStub skillStub = SkillStub.GetStub(skillId);
if (skillStub == null)
@@ -70,9 +70,9 @@ namespace BrewMonster
BMLogger.LogWarning($"CECAttacksMan::LoadSkillGfxOnDemand() - SkillStub not found for skill {skillId}");
return;
}
(string flyGFXPath, string hitGrdGFXPath, string hitGFXPath) = ElementSkill.GetAllGFX(skillId);
// Pass skillStub to LoadOneComposerAsync / 将技能存根传递给LoadOneComposerAsync
bool loaded = await m_pSkillGfxComposerMan.LoadOneComposerAsync((int)skillId, skillStub, flyGFXPath, hitGrdGFXPath, hitGFXPath);
if (!loaded)
@@ -80,18 +80,18 @@ namespace BrewMonster
BMLogger.LogWarning($"CECAttacksMan::LoadSkillGfxOnDemand() - Failed to load GFX for skill {skillId}");
}
}
public async void LoadAllSkillGfxAsync()
{
uint idSkill = 0;
var skillMap = SkillStub.GetMap();
if (skillMap == null || skillMap.Count == 0)
{
BMLogger.LogWarning("CECAttacksMan::LoadAllSkillGfxAsync() - Skill map is empty");
return;
}
BMLogger.Log($"CECAttacksMan::LoadAllSkillGfxAsync() - Loading GFX for {skillMap.Count} skills...");
int loadedCount = 0;
int failedCount = 0;
@@ -120,14 +120,14 @@ namespace BrewMonster
loadedCount++;
else
failedCount++;
// Yield every 10 skills to keep Unity responsive
if ((loadedCount + failedCount) % 10 == 0)
{
await UniTask.Yield();
}
}
BMLogger.Log($"CECAttacksMan::LoadAllSkillGfxAsync() - Complete. Loaded: {loadedCount}, Failed: {failedCount}");
//TODO: convert this part
/* char szMultiSectionFile[MAX_PATH] = { 0 };
@@ -164,7 +164,8 @@ namespace BrewMonster
//BMLogger.LogError("HoangDev: Update CECAttackEvent node.Value.m_bFinished: " + node.Value.m_bFinished);
if (node.Value.m_bFinished)
m_targets.Remove(node);
else {
else
{
node.Value.Tick(dwDeltaTime);
}
node = next;
@@ -185,7 +186,7 @@ namespace BrewMonster
// Always draw gizmos (not just when selected)
// 始终绘制辅助线(不仅在选择时)
int gizmoCount = SkillGfxGizmoDrawer.GetGizmoCount();
// Draw test gizmo at origin to verify OnDrawGizmos is working
// 在原点绘制测试辅助线以验证OnDrawGizmos是否工作
if (gizmoCount == 0 && Time.frameCount % 120 == 0) // Log every 2 seconds when no gizmos
@@ -195,7 +196,7 @@ namespace BrewMonster
Gizmos.color = Color.magenta;
Gizmos.DrawWireSphere(Vector3.zero, 1.0f);
}
if (gizmoCount > 0)
{
// Only log occasionally to avoid spam
@@ -207,7 +208,7 @@ namespace BrewMonster
}
SkillGfxGizmoDrawer.DrawGizmos();
}
/// <summary>
/// Draw gizmos when selected (for debugging)
/// 选择时绘制辅助线(用于调试)
@@ -552,26 +553,40 @@ namespace BrewMonster
/// 从文件加载组合器
/// </summary>
#if UNITY_EDITOR
string hitGfxName;
string flyGfxName;
string hitGrdGfxName;
public string hitGfxName;
public string flyGfxName;
public string hitGrdGfxName;
#endif
public async UniTask<bool> Load(SkillStub skillStub, string flyGFXPath, string hitGrdGFXPath, string hitGFXPath)
{
#if UNITY_EDITOR
flyGfxName = flyGFXPath;
hitGfxName = hitGFXPath;
hitGrdGfxName = hitGrdGFXPath;
#else
string flyGfxName = flyGFXPath;
string hitGfxName = hitGFXPath;
string hitGrdGfxName = hitGrdGFXPath;
#endif
// Load GFX prefabs / 加载GFX预制体
flyGFX = string.IsNullOrEmpty(flyGfxName) ? null : await AddressableManager.Instance.LoadPrefabAsync("gfx/" + flyGfxName);
hitGFX = string.IsNullOrEmpty(hitGfxName) ? null : await AddressableManager.Instance.LoadPrefabAsync("gfx/" + hitGfxName);
hitGrdGFX = string.IsNullOrEmpty(hitGrdGfxName) ? null : await AddressableManager.Instance.LoadPrefabAsync("gfx/" + hitGrdGfxName);
//BMLogger.LogError("HoangDev: Load A3DSkillGfxComposer GFX name: " + name);
if (flyGFX == null && !string.IsNullOrEmpty(flyGfxName))
{
flyGFX = Resources.Load<GameObject>("GFX/" + "PlaceHolder");
}
if (hitGFX == null && !string.IsNullOrEmpty(hitGfxName))
{
hitGFX = Resources.Load<GameObject>("GFX/" + "PlaceHolder");
}
if (hitGrdGFX == null && !string.IsNullOrEmpty(hitGrdGfxName))
{
hitGrdGFX = Resources.Load<GameObject>("GFX/" + "PlaceHolder");
}
// Read parameters from SkillStub / 从技能存根读取参数
if (skillStub != null)
@@ -582,26 +597,26 @@ namespace BrewMonster
m_AttHitMode = skillStub.m_AttHitMode;
m_dwFlyTime = skillStub.m_dwFlyTime;
m_bTraceTarget = skillStub.m_bTraceTarget;
// Clustering / 集群
m_FlyCluster.m_ulCount = skillStub.m_FlyClusterCount;
m_FlyCluster.m_dwInterv = skillStub.m_FlyClusterInterval;
m_HitCluster.m_ulCount = skillStub.m_HitClusterCount;
m_HitCluster.m_dwInterv = skillStub.m_HitClusterInterval;
// Behavior / 行为
m_bOneHit = skillStub.m_bOneHit;
m_bFadeOut = skillStub.m_bFadeOut;
m_bRelScl = skillStub.m_bRelScl;
m_fDefTarScl = skillStub.m_fDefTarScl;
// Area / 区域
/* m_param.m_bArea = skillStub.m_bArea;
m_param.m_Shape = skillStub.m_Shape;
m_param.m_vSize = skillStub.m_vSize;
// Param value / 参数值
m_param.value = skillStub.m_param.value;*/
/* m_param.m_bArea = skillStub.m_bArea;
m_param.m_Shape = skillStub.m_Shape;
m_param.m_vSize = skillStub.m_vSize;
// Param value / 参数值
m_param.value = skillStub.m_param.value;*/
}
else
{
@@ -676,7 +691,7 @@ namespace BrewMonster
int originalCount = targets.Count;
targets = validTargets;
for (int i = 0; i < targets.Count; i++)
{
var tar = targets[i];
@@ -776,10 +791,10 @@ namespace BrewMonster
}
// 计算缩放 / Calculate scale
/* if (m_bRelScl)
fScale = SkillGfxMan.InstanceSub.GetTargetScale(_Target) / m_fDefTarScl * m_fHitGfxScale;
else
fScale = m_fHitGfxScale;*/
/* if (m_bRelScl)
fScale = SkillGfxMan.InstanceSub.GetTargetScale(_Target) / m_fDefTarScl * m_fHitGfxScale;
else
fScale = m_fHitGfxScale;*/
// 根据目标类型决定是否显示特效 / Determine whether to show effects based on target type
if ((nCastTargetID != 0 && tar.idTarget != nCastTargetID)
@@ -865,7 +880,7 @@ public class CECAttackEvent
m_timeToBeFired = (uint)nTimeToBeFired;
m_timeToDoDamage = (uint)nTimeToDoDamage;
m_bFinished = false;
debugCounter = UnityEngine.Random.Range(0, 1000);
debugCounter = UnityEngine.Random.Range(0, 1000);
AddTarget(idTarget, dwModifier, nDamage);
}
@@ -1497,3 +1512,8 @@ public enum GfxSkillValType
enumGfxSkillFloat,
enumGfxSkillValTypeNum
};
@@ -420,13 +420,6 @@ namespace BrewMonster
m_pHitGfx = pHitGfx;
}*/
// ===== Helper functions (static) =====
// 辅助函数(静态)
/// <summary>
/// Get position by ID (player or NPC)
/// 根据ID获取位置(玩家或NPC)
/// </summary>
private static bool get_pos_by_id(
EC_ManPlayer pPlayerMan,
CECNPCMan pNPCMan,
@@ -531,7 +524,6 @@ namespace BrewMonster
/*A3DSkeletonHook* pHook = pNPC->GetSgcHook(szHanger, bChildHook, szHook);
if (!pHook)
break;
A3DSkinModel *pSkin = pNPC->GetSgcSkinModel(szHanger, bChildHook, szHook);
if (bRelHook)
vPos = pHook->GetAbsoluteTM() * pOffset;
@@ -540,7 +532,6 @@ namespace BrewMonster
vPos = pSkin->GetAbsoluteTM() * pOffset;
vPos = vPos - pSkin->GetAbsoluteTM().GetRow(3) + pHook->GetAbsoluteTM().GetRow(3);
}
return true;*/
break;
}
@@ -611,14 +602,9 @@ namespace BrewMonster
return true;
}
}
return false;
}
/// <summary>
/// Get scale by ID (height from AABB)
/// 根据ID获取缩放(从AABB获取高度)
/// </summary>
public static float _get_scale_by_id(
EC_ManPlayer pPlayerMan,
CECNPCMan pNPCMan,
@@ -747,7 +733,11 @@ namespace BrewMonster
m_pNPCMan = EC_ManMessageMono.Instance?.CECNPCMan;
}
public override void Dispose()
{
base.Dispose();
InstanceSub = null;
}
public A3DSkillGfxEvent GetEmptyEvent(GfxMoveMode mode)
{
int modeIndex = (int)mode;
@@ -60,7 +60,6 @@ namespace BrewMonster
}
if (Input.GetKeyDown(KeyCode.H))
{
BMLogger.LogError("Input.GetKeyDown(KeyCode.H)");
CycleSkillShortcuts();
}
#endif
@@ -703,7 +703,6 @@ namespace BrewMonster.Scripts.Managers
public string m_strDesc = ""; // Item description
public bool m_bIsInNPCPack; // true, this item is in NPC package
public bool m_bLocalDetailData; // true, data from GetDetailDataFromLocal
public int m_iCurEndurance; // Current endurance
public EC_Inventory m_pDescIvtr; // Inventory only used to get item description
@@ -739,7 +738,6 @@ namespace BrewMonster.Scripts.Managers
m_bIsInNPCPack = false;
m_bLocalDetailData = false;
m_pDescIvtr = null;
m_iCurEndurance = 0;
}
@@ -1274,7 +1272,6 @@ namespace BrewMonster.Scripts.Managers
#endregion
#region Simple property-style accessors (1:1 with C++)
public int GetCurEndurance() { return m_iCurEndurance; }
public int GetClassID() => m_iCID;
public int GetTemplateID() => m_tid;
@@ -104,14 +104,14 @@ namespace BrewMonster
}
private ElementSkill m_pSkillCore;
private int m_idSkill;
private int m_iLevel;
private int m_iCoolCnt;
private int m_iCoolTime;
private bool m_bCooling;
private int m_iChargeCnt;
private int m_iChargeMax;
private bool m_bCharging;
private int m_idSkill;
private int m_iLevel;
private int m_iCoolCnt;
private int m_iCoolTime;
private bool m_bCooling;
private int m_iChargeCnt;
private int m_iChargeMax;
private bool m_bCharging;
private static CECSkillStr l_SkillStr = new CECSkillStr();
@@ -196,6 +196,7 @@ namespace BrewMonster
m_iCoolCnt = iStartCnt;
m_bCooling = true;
}
public bool ValidWeapon(int idWeapon) { return m_pSkillCore.ValidWeapon(idWeapon); }
// Ready to be cast ?
public bool ReadyToCast()
@@ -290,10 +291,10 @@ namespace BrewMonster
return null;
StringBuilder sb = new StringBuilder(1024);
m_pSkillCore.GetIntroduction(sb, l_SkillStr);
m_pSkillCore.GetIntroduction(sb, l_SkillStr);
return sb;
}
public static StringBuilder GetDesc(int idSkill, int iLevel, StringBuilder szText, int iBufLen)
public static StringBuilder GetDesc(int idSkill, int iLevel, StringBuilder szText, int iBufLen)
{
if (szText == null || iBufLen == 0)
return null;
@@ -367,10 +368,6 @@ namespace BrewMonster
return m_pSkillCore != null ? m_pSkillCore.GetNativeName() ?? string.Empty : string.Empty;
}*/
public bool ValidWeapon(int idWeapon)
{
return m_pSkillCore != null && m_pSkillCore.ValidWeapon(idWeapon);
}
/*
public bool ValidShape(int iShape)
{
@@ -76,7 +76,7 @@ namespace BrewMonster.Scripts.Skills
public void SendHelloToSkillLearnNPC()
{
//BMLogger.LogError($"[Skill] Sent SEVNPC_HELLO to skill-learn NPC nid={m_skillLearnNPCNID}");
BMLogger.LogError($"[Skill] Sent SEVNPC_HELLO to skill-learn NPC nid={m_skillLearnNPCNID}");
if (m_skillLearnNPCNID != 0)
{
@@ -58,6 +58,13 @@ namespace BrewMonster.Scripts.Skills
return (int)tmp;
}
public override int GetItemCost() { return stub.itemcost; }
public override bool ValidWeapon(int idWeapon) { return stub.ValidWeapon(idWeapon); }
public override int GetMpCost() { return (int)stub.GetMpcost(this); }
public override bool IsAllowLand() { return stub.allow_land; }
public override bool IsAllowWater() { return stub.allow_water; }
public override bool IsAllowAir() { return stub.allow_air; }
public override int GetArrowCost() { return stub.arrowcost; }
public override bool GetNotuseInCombat() { return stub.notuse_in_combat; }
public int GetLevel() { return (int)level; }
public PlayerWrapper GetPlayer()
@@ -134,6 +134,7 @@ namespace BrewMonster
}
else
{
//BMLogger.LogError("HoangDev: QuickBar Skill CoolTime: " + (uint)pSkill.GetSkillID() + " : " + ElementSkill.GetIcon((uint)pSkill.GetSkillID()) + " CoolTime: " + pSkill.GetCoolingTime() + " CoolCnt: " + pSkill.GetCoolingCnt());
pClock.SetProgressPos(pSkill.GetCoolingTime() - pSkill.GetCoolingCnt());
}
}
@@ -1,4 +1,5 @@
using BrewMonster.Assets.PerfectWorld.Scripts.UI.GamePlay;
using BrewMonster.Network;
using BrewMonster.Scripts.Skills;
using BrewMonster.UI;
using CSNetwork.GPDataType;
@@ -56,7 +57,7 @@ namespace BrewMonster
{
uiManager.ShowMessageBox(new MessageBoxData()
{
Title = "MessageBox",
Title = "MessageBox",
Message = gameUIMan.GetStringFromTable(11327)
});
}
@@ -103,8 +104,9 @@ namespace BrewMonster
string str = GPDataTypeHelper.ReplacePercentD(GetStringFromTable(11326), needMoney, needSp);
var messagebox = uiManager.ShowMessageBox(new MessageBoxData()
{
Title = "Game_LearnSkill",
Title = "Game_LearnSkill",
Message = str,
OnClickedYes = () => UnityGameSession.c2s_SendCmdNPCSevLearnSkill(m_skillID)
});
messagebox.SetData((uint)m_skillID);
//GetGameUIMan()->MessageBox("Game_LearnSkill", str, //GetGameUIMan()->GetStringFromTable(231),
@@ -24,7 +24,6 @@ namespace BrewMonster
/// </summary>
public override void StartMove(Vector3 vHost, Vector3 vTarget)
{
BMLogger.LogError($"[SKILL_GFX_DEBUG] CGfxOnTargetMove.StartMove: Entry - host={vHost}, target={vTarget}, cluster={m_bOneOfCluser}, radius={m_fRadius}");
m_vPos = vTarget;
m_vMoveDir = vTarget - vHost;
@@ -32,7 +31,6 @@ namespace BrewMonster
if (Normalize(ref m_vMoveDir) == 0)
{
m_vMoveDir = Vector3.forward; // _unit_z
BMLogger.LogError($"[SKILL_GFX_DEBUG] CGfxOnTargetMove.StartMove: MoveDir was zero, using forward");
}
if (m_bOneOfCluser)
@@ -43,15 +41,12 @@ namespace BrewMonster
m_vOffset.z = Mathf.Sin(fRandAng) * fRadius;
m_vOffset.y = 0;
m_vPos += m_vOffset;
BMLogger.LogError($"[SKILL_GFX_DEBUG] CGfxOnTargetMove.StartMove: Cluster offset applied - offset={m_vOffset}, finalPos={m_vPos}");
}
else
{
m_vOffset = Vector3.zero;
BMLogger.LogError($"[SKILL_GFX_DEBUG] CGfxOnTargetMove.StartMove: No cluster offset, pos={m_vPos}");
}
BMLogger.LogError($"[SKILL_GFX_DEBUG] CGfxOnTargetMove.StartMove: Complete - pos={m_vPos}, dir={m_vMoveDir}");
}
/// <summary>
@@ -63,7 +58,6 @@ namespace BrewMonster
Vector3 oldPos = m_vPos;
m_vPos = vTargetPos + m_vOffset;
BMLogger.LogError($"[SKILL_GFX_DEBUG] CGfxOnTargetMove.TickMove: Updated pos from {oldPos} to {m_vPos} (target={vTargetPos}, offset={m_vOffset}), returning false (hit by timeout)");
return false; // C++ returns false — hit triggered by fly time timeout
}
+12 -4
View File
@@ -797,7 +797,7 @@ namespace BrewMonster
byte byPVPMask = glb_BuildPVPMask(bForceAttack);
Debug.Log($"HoangDev: Cast Skill ID={m_pPrepSkill.GetSkillID()}");
Debug.LogError($"HoangDev: Cast Skill ID={m_pPrepSkill.GetSkillID()}");
// Handle instant skills
if (m_pPrepSkill.IsInstant())
@@ -1172,13 +1172,21 @@ namespace BrewMonster
CECIvtrWeapon pWeapon =
(CECIvtrWeapon)m_pEquipPack.GetItem((int)IndexOfIteminEquipmentInventory.EQUIPIVTR_WEAPON);
if (pWeapon == null || pWeapon.GetCurEndurance() == 0)
if (pWeapon == null || pWeapon.CurEndurance == 0)
{
//BMLogger.LogError(GetName() + " CheckSkillCastCondition: Weapon major type ID = " + Info.weapon);
Info.weapon = 0;
}
else if (!CanUseEquipment(pWeapon, ref iReason))
Info.weapon = (iReason == 5) ? (int)pWeapon.GetDBMajorType().id : 0;
{
Info.weapon = (iReason == 5) ? (int)pWeapon.GetDBMajorType().id : 0; }
else
Info.weapon = (int)pWeapon.GetDBMajorType().id;
{
Info.weapon = (int)pWeapon.GetDBMajorType().id; }
//BMLogger.LogError(GetName() + " CheckSkillCastCondition: Weapon major type ID = " + Info.weapon);
// Get remaining arrow number
CECIvtrArrow pArrow =
(CECIvtrArrow)m_pEquipPack.GetItem((int)IndexOfIteminEquipmentInventory.EQUIPIVTR_PROJECTILE);
-6
View File
@@ -410,12 +410,6 @@ namespace BrewMonster
{
pointCam.rotation = Quaternion.identity;
}
#if UNITY_EDITOR
if (Input.GetKeyDown(KeyCode.C))
{
ApplySkillShortcut(1);
}
#endif
// Update cursor based on what's under mouse
EstimateCursor();
File diff suppressed because one or more lines are too long