diff --git a/client/webapp/js/engine/combat_skills.js b/client/webapp/js/engine/combat_skills.js --- a/client/webapp/js/engine/combat_skills.js +++ b/client/webapp/js/engine/combat_skills.js @@ -284,3 +284,4 @@ - function doDodge() { + function doDodge(invoker) { + if (player.isIFrame || (window.skillBarController && window.skillBarController.isSlotOnCooldown('dodge'))) return; if (typeof sfxEngine !== 'undefined') sfxEngine.playDodgeWhoosh(); else playAudioFx('dodge'); @@ -297,2 +298,2 @@ - if (window.skillBarController) window.skillBarController.triggerCooldown('dodge', 3.0); + if (!invoker && window.skillBarController) window.skillBarController.triggerCooldown('dodge', 3.0); } @@ -480,17 +481,5 @@ // Expose globals for external test runners & DevTools MCP - window.player = player; - window.monster = monster; - window.ASSETS = ASSETS; - window.doFire = doFire; - window.doThunder = doThunder; - window.doFrost = doFrost; - window.doDodge = doDodge; - window.doPrimaryAttack = doPrimaryAttack; - window.dodgeCharges = dodgeCharges; - window.bossHeavySlam = bossHeavySlam; - window.bossStagger = bossStagger; - window.btnSwapWeapon = btnSwapWeapon; - window.currentNearbyInteraction = () => currentNearbyInteraction; - window.executeNearbyInteraction = executeNearbyInteraction; - window.getAvailablePortalTargets = getAvailablePortalTargets; + Object.assign(window, { + player, monster, ASSETS, doFire, doThunder, doFrost, doDodge, doPrimaryAttack, + dodgeCharges, bossHeavySlam, bossStagger, btnSwapWeapon, + currentNearbyInteraction: () => currentNearbyInteraction, executeNearbyInteraction, getAvailablePortalTargets + }); diff --git a/client/webapp/js/engine/monster_system.js b/client/webapp/js/engine/monster_system.js --- a/client/webapp/js/engine/monster_system.js +++ b/client/webapp/js/engine/monster_system.js @@ -237,4 +237,8 @@ - } else if (m.attackCooldown <= 0) { - // Attack strike on player! - m.attackCooldown = 1.75 + Math.random() * 0.5; - executeMonsterAttackOnPlayer(m); + } else if (m.attackCooldown <= 0) { + m.attackCooldown = (m.isBoss ? 2.5 : 1.75) + Math.random() * 0.5; + if (typeof window.TelegraphRenderer !== 'undefined' && typeof window.TelegraphRenderer.startMonsterAttack === 'function') { + window.TelegraphRenderer.startMonsterAttack(m, player, executeMonsterAttackOnPlayer); + } else { + executeMonsterAttackOnPlayer(m); + } } @@ -290,10 +294,11 @@ - if (player.isIFrame) { - // Evasion success! + if (player.isIFrame === true || (player.iFrameTimer && player.iFrameTimer > 0)) { if (typeof sfxEngine !== 'undefined') sfxEngine.playDodgeWhoosh(); else if (typeof playAudioFx === 'function') playAudioFx('dodge'); const pPos = worldToIso(player.wx, player.wy); if (typeof spawnDamageText === 'function') { spawnDamageText('NÉ ĐÒN! (i-frame)', pPos.x, pPos.y - 45, '#38bdf8', false); } + if (typeof spawnParticles === 'function') spawnParticles('phantom', player.wx, player.wy, 16); return; }