Fix some bug
This commit is contained in:
@@ -59,6 +59,11 @@ namespace BrewMonster
|
||||
[Tooltip("When enabled, hides skills that fail weapon/form/move-env restrictions. Disable to show ALL positive skills regardless of restrictions.")]
|
||||
[SerializeField] private bool filterByRestrictions = false;
|
||||
|
||||
[Tooltip("Match CDlgSkillSubList god/evil path: false = base+god ranks, true = base+evil ranks.")]
|
||||
[SerializeField] private bool isEvilSkillPath;
|
||||
|
||||
[SerializeField] private int skillCatalogLevel = 1;
|
||||
|
||||
/// <summary>
|
||||
/// World position of the draggable target marker, read by CECSkillGfxMan.get_pos_by_id.
|
||||
/// 可拖动目标标记的世界坐标,由 CECSkillGfxMan.get_pos_by_id 读取。
|
||||
@@ -101,6 +106,19 @@ namespace BrewMonster
|
||||
gameRun.RegisterAnimSceneHostPlayer(player);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Anim scene host swap: keep panel player reference in sync with bootstrap.
|
||||
/// 动画场景切换角色时同步面板上的主角引用。
|
||||
/// </summary>
|
||||
public void SetHostPlayer(CECHostPlayer host)
|
||||
{
|
||||
if (host == null)
|
||||
return;
|
||||
|
||||
player = host;
|
||||
RegisterSceneHostWithGameRun();
|
||||
}
|
||||
|
||||
/// <summary>Target id for <see cref="LocalCastSkill"/> / GFX composer (self = host cid, else marker NPC id).</summary>
|
||||
private int ResolveLocalCastTargetId(CECSkill skill)
|
||||
{
|
||||
@@ -114,14 +132,11 @@ namespace BrewMonster
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Polls every 0.5 s until the host player has skills and CECGameUIMan is initialized,
|
||||
/// then calls Refresh() once. If no server skill data arrives within <see cref="k_InjectFallbackSecs"/>
|
||||
/// seconds, injects all config skills directly from SkillStub.map so the panel works offline.
|
||||
/// Polls until CECGameUIMan is ready and the host has skills (server, skill model, or config fallback).
|
||||
///
|
||||
/// 每 0.5 秒轮询,直到主角已有技能且 CECGameUIMan 初始化完毕,再调用一次 Refresh()。
|
||||
/// 若 k_InjectFallbackSecs 秒内未收到服务端技能数据,则直接从 SkillStub.map 注入所有配置技能,以便离线使用。
|
||||
/// 轮询直到 UI 图集与技能数据就绪(服务端、CECHostSkillModel 或配置回退)。
|
||||
/// </summary>
|
||||
private const float k_InjectFallbackSecs = 2f;
|
||||
private const float k_RefreshWaitTimeoutSecs = 30f;
|
||||
private IEnumerator RefreshWhenReady()
|
||||
{
|
||||
var wait = new WaitForSeconds(0.5f);
|
||||
@@ -135,17 +150,23 @@ namespace BrewMonster
|
||||
yield return wait;
|
||||
}
|
||||
|
||||
// Wait for skills, but fall back to config injection after timeout.
|
||||
// 等待技能数据,超时后回退到配置注入。
|
||||
while (player != null && player.GetPositiveSkillNum() == 0)
|
||||
ResolveHostPlayerReference();
|
||||
|
||||
// Wait for skills: server list, CECHostSkillModel catalog (anim scene), or config fallback.
|
||||
// 等待技能:服务端列表、CECHostSkillModel 目录(动画场景)或配置回退。
|
||||
while (player != null && !HasSkillCatalogOrPositiveSkills())
|
||||
{
|
||||
if (elapsed >= k_InjectFallbackSecs)
|
||||
if (TryInjectFromSkillModel())
|
||||
break;
|
||||
|
||||
if (elapsed >= k_RefreshWaitTimeoutSecs)
|
||||
{
|
||||
Debug.Log("[SkillTriggerPanel] No server skills after " +
|
||||
$"{k_InjectFallbackSecs}s — injecting all config skills for offline debug.");
|
||||
Debug.LogWarning("[SkillTriggerPanel] No skills after " +
|
||||
$"{k_RefreshWaitTimeoutSecs}s — falling back to SkillStub.map injection.");
|
||||
player.InjectDebugSkillsFromConfig();
|
||||
break;
|
||||
}
|
||||
|
||||
elapsed += 0.5f;
|
||||
yield return wait;
|
||||
}
|
||||
@@ -153,6 +174,36 @@ namespace BrewMonster
|
||||
Refresh();
|
||||
}
|
||||
|
||||
private void ResolveHostPlayerReference()
|
||||
{
|
||||
if (player != null)
|
||||
return;
|
||||
|
||||
player = EC_Game.GetGameRun()?.GetHostPlayer();
|
||||
}
|
||||
|
||||
private bool HasSkillCatalogOrPositiveSkills()
|
||||
{
|
||||
if (player != null && player.GetPositiveSkillNum() > 0)
|
||||
return true;
|
||||
|
||||
List<int> catalog = CECHostSkillModel.Instance?.CollectSkillSubListSkillIds(isEvilSkillPath);
|
||||
return catalog != null && catalog.Count > 0;
|
||||
}
|
||||
|
||||
private bool TryInjectFromSkillModel()
|
||||
{
|
||||
if (player == null)
|
||||
return false;
|
||||
|
||||
List<int> catalog = CECHostSkillModel.Instance?.CollectSkillSubListSkillIds(isEvilSkillPath);
|
||||
if (catalog == null || catalog.Count == 0)
|
||||
return false;
|
||||
|
||||
player.InjectSkillsFromSkillModel(skillCatalogLevel, isEvilSkillPath);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads every skill defined in SkillStub.map (config) directly into the player's skill list,
|
||||
/// bypassing the server skill message. Use this when testing locally without a server.
|
||||
@@ -171,6 +222,46 @@ namespace BrewMonster
|
||||
Refresh();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rebuild host positive skills from <see cref="CECHostSkillModel"/> (same catalog as CDlgSkillSubList) and refresh the grid.
|
||||
/// AnimScenePlayerBootstrap calls this after each model / role switch.
|
||||
///
|
||||
/// 从 CECHostSkillModel 重建主角正向技能并刷新网格(与 CDlgSkillSubList 相同目录)。
|
||||
/// </summary>
|
||||
[ContextMenu("Debug: Refresh From Skill Model")]
|
||||
public void RefreshFromSkillModel(int level = -1)
|
||||
{
|
||||
ResolveHostPlayerReference();
|
||||
if (player == null)
|
||||
{
|
||||
Debug.LogWarning("[SkillTriggerPanel] RefreshFromSkillModel: no host player.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (level > 0)
|
||||
skillCatalogLevel = level;
|
||||
|
||||
player.InjectSkillsFromSkillModel(skillCatalogLevel, isEvilSkillPath);
|
||||
|
||||
List<CECSkill> catalogSkills = player.BuildSkillSubListSkills(skillCatalogLevel, isEvilSkillPath);
|
||||
PopulateSkillGrid(catalogSkills, catalogSkills.Count);
|
||||
}
|
||||
|
||||
public void SetEvilSkillPath(bool isEvil)
|
||||
{
|
||||
isEvilSkillPath = isEvil;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reload from CECHostSkillModel and optionally hide skills that fail weapon/form/env checks.
|
||||
/// 从技能目录重新加载;applyRestrictions 为 true 时按武器/形态/环境过滤。
|
||||
/// </summary>
|
||||
public void ResetSkillsFromSkillModel(bool applyRestrictions, int level = -1)
|
||||
{
|
||||
filterByRestrictions = applyRestrictions;
|
||||
RefreshFromSkillModel(level);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears and repopulates the skill grid from the host player's current positive skill list.
|
||||
/// Call again after equipping a different weapon or changing shape/form.
|
||||
@@ -197,12 +288,14 @@ namespace BrewMonster
|
||||
return;
|
||||
}
|
||||
|
||||
// Clear existing buttons / 清空已有按钮
|
||||
foreach (Transform child in skillGridContainer)
|
||||
Destroy(child.gameObject);
|
||||
var catalogSkills = player.BuildSkillSubListSkills(skillCatalogLevel, isEvilSkillPath);
|
||||
if (catalogSkills.Count > 0)
|
||||
{
|
||||
PopulateSkillGrid(catalogSkills, catalogSkills.Count);
|
||||
return;
|
||||
}
|
||||
|
||||
int total = player.GetPositiveSkillNum();
|
||||
|
||||
if (total == 0)
|
||||
{
|
||||
Debug.LogWarning("[SkillTriggerPanel] GetPositiveSkillNum() = 0. " +
|
||||
@@ -211,6 +304,22 @@ namespace BrewMonster
|
||||
return;
|
||||
}
|
||||
|
||||
var positiveSkills = new List<CECSkill>(total);
|
||||
for (int i = 0; i < total; i++)
|
||||
{
|
||||
CECSkill skill = player.GetPositiveSkillByIndex(i);
|
||||
if (skill != null)
|
||||
positiveSkills.Add(skill);
|
||||
}
|
||||
|
||||
PopulateSkillGrid(positiveSkills, total);
|
||||
}
|
||||
|
||||
private void PopulateSkillGrid(IReadOnlyList<CECSkill> skills, int totalListed)
|
||||
{
|
||||
foreach (Transform child in skillGridContainer)
|
||||
Destroy(child.gameObject);
|
||||
|
||||
CECGameUIMan uiMan = CECUIManager.Instance?.GetInGameUIMan();
|
||||
if (uiMan == null)
|
||||
{
|
||||
@@ -221,9 +330,9 @@ namespace BrewMonster
|
||||
|
||||
int added = 0;
|
||||
int filtered = 0;
|
||||
for (int i = 0; i < total; i++)
|
||||
for (int i = 0; i < skills.Count; i++)
|
||||
{
|
||||
CECSkill skill = player.GetPositiveSkillByIndex(i);
|
||||
CECSkill skill = skills[i];
|
||||
if (skill == null)
|
||||
continue;
|
||||
|
||||
@@ -235,21 +344,19 @@ namespace BrewMonster
|
||||
|
||||
GameObject cell = Instantiate(skillButtonPrefab, skillGridContainer);
|
||||
|
||||
// --- Icon ---
|
||||
string iconName = skill.GetIconFile();
|
||||
if (!string.IsNullOrEmpty(iconName))
|
||||
{
|
||||
Sprite icon = uiMan.GetIcon(iconName, EC_GAMEUI_ICONS.ICONS_SKILL);
|
||||
Image cellImage = GetIconImage(cell);
|
||||
Debug.Log("[SkillTriggerPanel] icon = " + (icon == null) + "cellImage = " + (cellImage == null));
|
||||
if (cellImage != null && icon != null)
|
||||
cellImage.sprite = icon;
|
||||
}
|
||||
else{
|
||||
else
|
||||
{
|
||||
Debug.LogWarning("[SkillTriggerPanel] skill.GetIconFile() is empty for skill " + skill.GetSkillID());
|
||||
}
|
||||
|
||||
// --- Label ---
|
||||
Text cellText = cell.GetComponentInChildren<Text>();
|
||||
if (cellText != null)
|
||||
{
|
||||
@@ -259,7 +366,6 @@ namespace BrewMonster
|
||||
: $"{skillName}\nLv{skill.GetSkillLevel()}";
|
||||
}
|
||||
|
||||
// --- Button ---
|
||||
CECSkill captured = skill;
|
||||
Button btn = cell.GetComponentInChildren<Button>();
|
||||
if (btn != null)
|
||||
@@ -269,7 +375,7 @@ namespace BrewMonster
|
||||
}
|
||||
|
||||
Debug.Log($"[SkillTriggerPanel] Refreshed: {added} buttons added " +
|
||||
$"({filtered} filtered by restrictions, {total} total positive skills).");
|
||||
$"({filtered} filtered by restrictions, {totalListed} catalog/server skills).");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -294,7 +400,7 @@ namespace BrewMonster
|
||||
if (weapon != null && weapon.CurEndurance > 0)
|
||||
weaponId = (int)weapon.GetDBMajorType().id;
|
||||
}
|
||||
|
||||
|
||||
// Fake unlimited resources but keep real weapon / form / env values
|
||||
// 伪造无限资源,但保留真实的武器/形态/环境值
|
||||
UseRequirement fakeInfo = new UseRequirement
|
||||
@@ -364,21 +470,21 @@ namespace BrewMonster
|
||||
if (!animOk)
|
||||
Debug.LogWarning($"[SkillTriggerPanel] PlaySkillCastAction returned false for skill {skillId} — animation may not play.");
|
||||
|
||||
// 2. Trigger VFX via the GFX composer — bypasses network entirely
|
||||
// 通过特效组合器触发特效,完全绕过网络
|
||||
var composerMan = CECAttacksMan.Instance?.GetSkillGfxComposerMan();
|
||||
if (composerMan != null)
|
||||
{
|
||||
var targets = new List<TARGET_DATA>
|
||||
{
|
||||
new TARGET_DATA { idTarget = targetId, dwModifier = 0, nDamage = 0 }
|
||||
};
|
||||
composerMan.Play(skillId, player.GetCharacterID(), targetId, targets);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning($"[SkillTriggerPanel] composerMan is null — VFX skipped for skill {skillId}.");
|
||||
}
|
||||
// // 2. Trigger VFX via the GFX composer — bypasses network entirely
|
||||
// // 通过特效组合器触发特效,完全绕过网络
|
||||
// var composerMan = CECAttacksMan.Instance?.GetSkillGfxComposerMan();
|
||||
// if (composerMan != null)
|
||||
// {
|
||||
// var targets = new List<TARGET_DATA>
|
||||
// {
|
||||
// new TARGET_DATA { idTarget = targetId, dwModifier = 0, nDamage = 0 }
|
||||
// };
|
||||
// composerMan.Play(skillId, player.GetCharacterID(), targetId, targets);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// Debug.LogWarning($"[SkillTriggerPanel] composerMan is null — VFX skipped for skill {skillId}.");
|
||||
// }
|
||||
|
||||
// 3. After 2s, play the release / 施放起+落 attack animation chain (local-only).
|
||||
// 2 秒后播放施放攻击动画链(仅本地)。
|
||||
@@ -397,20 +503,20 @@ namespace BrewMonster
|
||||
|
||||
// first try to find if there is already a skill attack event in attackman
|
||||
CECAttackerEvents attackerEvents = CECAttacksMan.Instance.FindAttackByAttacker(hostPlayer.GetPlayerInfo().cid);
|
||||
// if (attackerEvents)
|
||||
// {
|
||||
// pAttack = attackerEvents.Find(skillId, 0);
|
||||
// if (pAttack != null)
|
||||
// {
|
||||
// // Ãæ¹¥»÷µÄ·ÇµÚÒ»´ÎÉ˺¦ÏûÏ¢
|
||||
// pAttack.AddTarget(DEBUG_TARGET_ID, 1, 1);
|
||||
// goto EXIT;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// attackerEvents.Signal();
|
||||
// }
|
||||
// }
|
||||
if (attackerEvents)
|
||||
{
|
||||
pAttack = attackerEvents.Find(skillId, 0);
|
||||
if (pAttack != null)
|
||||
{
|
||||
// Ãæ¹¥»÷µÄ·ÇµÚÒ»´ÎÉ˺¦ÏûÏ¢
|
||||
pAttack.AddTarget(DEBUG_TARGET_ID, 1, 1);
|
||||
goto EXIT;
|
||||
}
|
||||
else
|
||||
{
|
||||
attackerEvents.Signal();
|
||||
}
|
||||
}
|
||||
if (ElementSkill.IsGoblinSkill((uint)skillId) &&
|
||||
ElementSkill.GetType((uint)skillId) == 2)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user