18 KiB
18 KiB
Update: Special Projectile Trail
SPECIAL_EFFECT.PROJECTILE.TRAILcontrols optional afterimages for the moving special projectile. Each trail copy uses the projectile's current texture frame, scale, rotation, and flip state.- Trail objects are visual-only combat objects: they fade out and self-dispose, but they do not participate in hit detection.
TRAIL.INTERVAL_MSandTRAIL.LIFETIME_MSbound how many afterimages can exist at once.
Update: Split Special Projectile Visual Configs
- Special projectile visual asset settings are separated by caster type. Melee visual sheets are configured under
SPECIAL_EFFECT.MELEE; ranged visual sheets are configured underSPECIAL_EFFECT.RANGE. SPECIAL_EFFECT.PROJECTILEnow carries shared projectile behavior only: hold time, acceleration/ease, fallback speed, target density area, travel clamp, hit radius, max lifetime, and optional trail visuals.
Update: One-Shot Accelerating Special Projectile
SPECIAL_EFFECT.MELEE.REPEAT = 0makes melee special sprites play once.special-melee-effect-1currently hasframeSequencecommented out, so it uses the sprite sheet's natural frame order.- Special projectile movement now uses a tween instead of constant
physics.moveTo.SPECIAL_EFFECT.PROJECTILE.startHoldMskeeps the effect stationary for the pre-launch tell,travelDurationMscontrols the launch duration when set, andmovementEasecontrols the acceleration curve. IftravelDurationMsis unset, movement falls back tospeed. - Projectile hit checks still run from the scene UPDATE event while the tween moves the sprite, so instant-kill path detection remains active during acceleration.
Update: Special Effect Frame Sequence Refresh
createSpecialAnimation()now rebuilds a special animation when the existing Phaser global animation no longer matches the configured frames, repeat count, or frame rate. This prevents stale animation keys from hidingframeSequenceedits.frameSequencevalues stay 1-based in config and are converted withgenerateFrameNumbers(..., { frames }), so repeated frames are preserved when a special asset enables a custom sequence.
Update: Special Effect Frame Rate And Render Budget
SPECIAL_EFFECT.FRAME_RATE_MULTIPLIERmultiplies only special-effect animation frame rates. Caster sparkle, melee special sprites, and ranged special projectile frames can play faster or slower without changing caster hold time, launch delay, projectile movement speed, travel distance, or cleanup timers.SPECIAL_EFFECT.FOCUS_LAYER.BLUR_MAX_FIGHTERScaps whenspecialEffects.jscreates the full-arena blurred render-texture snapshot. Above that living-fighter count, the special focus keeps the dim layer and raised caster but skips the expensive blur pass.- Special projectile hit checks prefer
scene.combatTargetIndexand scan only spatial cells around the projectile segment, falling back toscene.fighterswhen no index exists.
Update: Special Effect Projectile
specialEffects.jsowns the one-shot special effect flow: asset preload/animation creation, random live-match scheduling, underdog caster selection, caster pose lock, launch visuals, projectile path checks, and cleanup.SPECIAL_EFFECTinsrc/constants.jstunes trigger timing, caster Hurt-frame hold, camera zoom, melee projectile assets, ranged projectile asset scale/speed/travel distance/hit radius, target density area, arena edge padding, and lifetime.WORLD_EFFECT.SPECIALpoints to the same config object.- Casters must be living, non-elite, non-magic fighters from teams that are not currently tied for first by represented living count. When
SPECIAL_EFFECT.CASTER.BALANCE_NON_MAGIC_TYPESis enabled, caster selection first picks among available non-magic types and then picks a fighter from that type, preventing the larger melee roster from overwhelming ranged special casts. If no caster exists at the chosen time, the timer retries within the configured window instead of firing multiple times. - Special casters receive realtime invulnerability for
SPECIAL_EFFECT.CASTER.INVULNERABLE_MS.combat.jschecks that window in normal attacks, world-effect damage, and special instant kills, whileworldEffects.jsalso skips frost survivor effects for invulnerable fighters. - While the caster holds the Hurt frame,
specialEffects.jspauses fighter AI, Arcade Physics, the scene clock, existing combat-object physics velocity, combat-object animations, and combat-object tweens. Existing combat/world delayed calls and already-falling meteor/frost tweens stop advancing until the realtime preparation hold releases into the attack animation. - The Hurt-frame preparation also spawns a caster sparkle overlay from
public/assets/effects/special/effect.png. Its animation uses the 1-based frame sequence[2, 3, 4]only, positions near the caster's eyes throughSPECIAL_EFFECT.CASTER_SPARKLE, and is disposed before the attack animation starts. - Caster emphasis uses
SPECIAL_EFFECT.FOCUS_LAYER:specialEffects.jssnapshots the current battlefield into a render texture, applies Phaser Blur FX when available, adds a dim layer, and raises the caster above both layers until cleanup. - The special camera does not follow the projectile. When projectile movement begins,
zoomOutSpecialEffectCameraFocus()zooms out in place usingSPECIAL_EFFECT.CAMERA.PROJECTILE_VIEW_ZOOMandPROJECTILE_ZOOM_OUT_MSso the projectile remains readable without dragging the camera off the arena. - Melee special projectile effects can define 1-based
frameSequencearrays.specialEffects.jsconverts them to Phaser frames so specific frames can be repeated for readability. The projectile'sstartHoldMskeeps it visible at the caster before travel begins. - At target-selection time, the special projectile scans living enemies with a summed-area table and locks onto the
SPECIAL_EFFECT.PROJECTILE.targetAreaTilessquare containing the highest representedstackCountpopulation. The moving projectile visual is type-based: melee casters fire one randomSPECIAL_EFFECT.MELEE.ASSETSsprite, while ranged casters useSPECIAL_EFFECT.RANGE. Movement uses a tweened Arcade Physics sprite, matching normal ranged projectile path-update checks while allowing acceleration, and projectile travel is cut to the arena bounds usingarenaEdgePadding. - The special projectile calls
applySpecialEffectInstantKill()fromcombat.js, so instant kills still use the normal death animation, death-stat recording, kill log attribution when there is a surviving caster, split-on-death behavior, scoreboard refresh, and match-finish checks.
Update: Elite Magic Attack Effect Scale
combat.jsresolves instant-spell attack effect scale through constants instead of hard-codingFIGHTER.SCALE.- Normal spell effects use
FIGHTER.SCALE * FIGHTER.ATTACK_EFFECT_SCALE_MULTIPLIER. - Elite magic spell effects additionally multiply by
FIGHTER.ELITE.ATTACK_EFFECT_SCALE_MULTIPLIER, keeping caster body scale and effect scale separately tunable.
Update: Elite Target Damage And Density
combat.jsusesfighter.isEliteto split damage rules. Elite critical hits deal the greater of the ordinary hit orCOMBAT.CRITICAL_DAMAGE_PERCENTof max HP; normal critical hits dealNORMAL_CRITICAL_DAMAGE_MULTIPLIERtimes the ordinary hit.- Elite attack and movement speed are calculated through
FIGHTER.ELITE.ATTACK_SPEED_*andMOVE_SPEED_*constants. Each multiplier is additive:0removes its added stack bonus, while1applies its configured exponent. - Elite direct kills trigger a kill splash at the killed fighter's body position. The splash deals
COMBAT.ELITE_KILL_SPLASH_DAMAGE_PERCENTof that killed fighter's max HP to living enemies insideCOMBAT.ELITE_KILL_SPLASH_RADIUS; splash kills are recorded normally, recursive splash chaining is controlled byELITE_KILL_SPLASH_CHAIN_ENABLED, and the optional visual uses square pixel dots rather than smooth circles. - Kills still record the attacker/defender and drive match resolution, but
COMBAT.KILL_REWARD_ENABLED = falseprevents heal effects, scale growth, and kill-derived speed multipliers in compressed elite battles. worldEffects.jspasses an effect type intoapplyWorldEffectDamage(): normal targets retain fixed fire/frost damage, while elite targets takeWORLD_EFFECT.METEOR_DAMAGE_PERCENTorFROST_DAMAGE_PERCENTof max HP.- Dense-area target scanning adds each fighter's represented
stackCountinto its tile, preventing compressed armies from disappearing from meteor/frost targeting pressure.
Update: Dense-Area Meteor Barrage
worldEffects.jsaggregates living fighters on the arena tile grid and uses a summed-area scan to select theWORLD_EFFECT.AREA_TILESsquare with the highest population.- That selected square is a warning/focus area. Each fire or frost event schedules
WORLD_EFFECT.IMPACT_COUNT_MINtoIMPACT_COUNT_MAXsmaller strikes inside it. - Tune the large warning visibility with
WORLD_EFFECT.WARNING_DURATION_MS, actual damage/frost footprints withWORLD_EFFECT.IMPACT_AREA_TILES, sprite size withWORLD_EFFECT.IMPACT_VISUAL_SCALE, strike spacing withWORLD_EFFECT.IMPACT_STAGGER_MS, and per-strike variation withWORLD_EFFECT.SIZE_SCALE_VARIANCE. WORLD_EFFECT.INTERVALsets the delay before the first barrage; subsequent normal barrages useWORLD_EFFECT.REPEAT_INTERVAL, withSUDDEN_DEATH.INTERVAL_MStaking over once sudden death is active.- Meteor impact shake uses the same size multiplier, scaling from
WORLD_EFFECT.METEOR_SHAKE_DURATION_MSandWORLD_EFFECT.METEOR_SHAKE_INTENSITY.
Update: Large Battle Targeting
combat.jsnow prepares a per-frame target spatial index throughprepareCombatFrame(scene).resolveTargetEnemy()keeps valid cached targets until their scan interval expires, then immediately looks up a fresh nearest enemy through the spatial grid.- Nearest enemy lookup searches grid cells outward from the fighter's current cell, with full-array scanning kept only as a fallback when no frame index exists.
- Large-battle corpse cleanup uses
PERFORMANCE.LARGE_BATTLE_FIGHTER_THRESHOLDandPERFORMANCE.LARGE_BATTLE_DEAD_DESPAWN_DELAY_MSfromsrc/constants.js.
Update: Team Shadow Animations And Frost Tint
- Dead fighters keep their death animation/corpse state at initial opacity, then fade out until
combat.jsremoves them fromscene.fightersand destroys the sprite. - Tune that fade/despawn lifetime with
FIGHTER.DEAD_DESPAWN_DELAY_MSand the final alpha withFIGHTER.DEAD_DESPAWN_ALPHAinsrc/constants.js. combat.jsresolves fighter animation keys throughensureFighterTeamAnimation()so every action can use the team-shadow baked texture generated from the original spritesheet.playIfNeeded()compares against the team-shadow animation key. This avoids switching back to the original non-team-colored spritesheet when fighters move, attack, take damage, or die.- Frost stun remains a body tint effect in
worldEffects.js. Since team identity is baked into the floor shadow pixels, there is noteamMarkertint state to update or restore. - The removed
teamMarkerdisplay object means death handling no longer needs to hide or destroy a separate marker. HUD cleanup only owns health-bar objects because battlefield name labels are no longer created.
Update: Focused Combat Effects In Large Battles
combat.jsexposes supplemental combat visuals only while a large battle is inside the temporary meteor camera-focus window.- Outside that window, large battles skip critical labels, instant-spell sprites, kill-heal sprites, and kill-growth tweens while retaining underlying damage calculations. Kill rewards are globally disabled by the elite policy.
- World-effect meteor/frost visuals remain visible, and projectile objects remain enabled because projectiles currently participate in hit detection.
Context: Combat System
1. 모듈별 상세 역할 (src/game/combat/)
combat.js: 전투 AI, 피해 계산, 처치 기록 및 비활성화된 보너스 경로를 담당합니다.fighterStats.js에서 해석한 역할별 수치로 이동, 공격, 투사체 발사 등을 처리합니다.combatSettings.js: 전투 속도 배율 등 런타임 전투 설정을 관리합니다.arenaFinalCombatEffects.js: 최종 교전 시 슬로우 모션 등 연출 효과를 담당합니다. 수학적인 이징(easing) 함수와 물리 시간 배율 계산을 포함합니다.worldEffects.js: 실제 전투에서 설정 주기마다 생존자 밀집 구역을 탐색하고 화염/냉기 소형 메테오 포격을 실행하며, 대각선 낙하 연출, 개별 탄착 판정, 냉기 동결과 감속 구역 수명주기를 처리합니다.
2. 주요 로직 구현 세부 사항
전투 AI 및 유닛 동작
updateFighter(): 가장 가까운 적을 찾아 이동하거나 공격하는 유닛 AI의 핵심입니다.applyHit(): 일반 공격 피해량은 공격자의melee/ranged/magic프로필 피해량 범위에서 계산합니다. 치명타 적중은Critical!을 표시하고, 일반 대상에는 일반 피해의 2배, elite 대상에는 최대 체력 비례 피해를 적용합니다.- 역할별 기본값:
src/constants.js의FIGHTER_TYPE_STATS에서 체력, 이동속도, 사거리, 공격 쿨다운, 피해량, 치명타 확률, 발동 지연을 독립적으로 조절합니다. 투사체 속도는ranged, 효과 적중 지연은magic프로필에 포함됩니다. projectilePathHitsDefender(): 투사체가 대상을 스쳐 지나가지 않도록 궤적(Line)과 히트박스(Rectangle) 겹침 검사를 수행합니다.
처치 보너스 정책
- elite 압축 전투에서는
COMBAT.KILL_REWARD_ENABLED가false이므로 처치자 체력 회복, 크기 성장, 공격속도/이동속도 보너스와 회복 이펙트가 적용되지 않습니다. - 킬로그, 사망 통계, 분열 판정, 승패 판정은 처치 보너스와 별개로 계속 처리됩니다.
applyKillReward()와 관련 상수는 향후 별도의 비압축 모드에서 명시적으로 활성화할 수 있는 경로로만 보존합니다.
월드 이펙트
- 발동 규칙: 프리뷰가 아닌 실제 전투에서 시작 후 첫 포격은
WORLD_EFFECT.INTERVAL이 지난 뒤 발생하고, 이후 일반 포격은WORLD_EFFECT.REPEAT_INTERVAL간격으로 발생합니다. 각 포격은AREA_TILES크기의 모든 후보 구역을 타일 누적합으로 평가해, 생존 캐릭터가 가장 많이 모인 범위를 선택합니다. 같은 밀도의 후보가 여러 개일 때만 그 후보 사이에서 무작위로 고릅니다. - 포격 판정: 선택된 큰 범위는 경고 표시와 카메라 포커스 대상으로 사용되고, 내부에 투하되는 작은 탄착 영역만 피해, 기절, 냉기 감속을 처리합니다. 이 때문에 넓은 밀집지대를 위협하면서도 영역 전체를 즉시 동일 피해로 덮지 않습니다.
- 서든 데스 (Sudden Death):
- 조건: 매치 시작 후
WORLD_EFFECT.SUDDEN_DEATH.TRIGGER_MS시간이 경과하면 서든 데스 상태에 진입합니다 (활성화 시). - 효과: 메테오 투하 주기가
SUDDEN_DEATH.INTERVAL_MS로 단축되며,FORCE_FROST설정 시 빙결 효과를 가진 냉기 메테오가 집중적으로 생성됩니다. - 목적: 장기전을 방지하고 전장에 무작위 변수를 극대화하여 물량 중심 팀에게 리스크를 부여합니다.
- 조건: 매치 시작 후
- 낙하 방향과 크기: 대상이 전장 좌측 반면(2, 3사분면)이면 화살표가 좌상단에서 우하단으로, 우측 반면(1, 4사분면)이면 좌우 반전되어 우상단에서 좌하단으로 이동합니다. 스프라이트를 45도로 기울이고 전용 시각 배율을 사용해 전역 마법 규모로 표현합니다.
- 화염 메테오:
world_Effect.png의 소형 탄착 애니메이션 3~4개가 밀집 경고 구역 내부로 순차 낙하합니다. 각 탄착은 크기에 따른 화면 흔들림과 개별 영역 고정 피해를 적용합니다. 환경 피해로 인한 사망은 킬 보상을 지급하지 않지만 사망 통계와 승패 판정에는 반영됩니다. - 냉기 메테오:
world_Effect_2.png의 소형 탄착 애니메이션들이 같은 방식으로 낙하합니다. 개별 탄착 피해를 입고 생존한 대상은 얼음색으로 바뀐 채 설정 시간 동안 기절하며, 각 탄착점에 남는 냉각지대 안에서는 공격속도와 이동속도 감속 배율을 적용합니다.
최종교전 슬로우모션
COMBAT.FINAL_SLOW_MOTION_ENABLED가 활성화된 경우:
- 최종교전 상태에서 공격 모션이 시작될 때 전역 time scale을 낮춥니다.
- 진입/유지/복귀 속도 램프(Ease)를 적용합니다.
- Arcade Physics는 timeScale 방향이 반대라 물리 이동에는 역수 배율을 적용합니다.
3. 유지보수 규칙
- 처치 보너스: elite 압축 규칙을 유지하는 동안
src/constants.js의COMBAT.KILL_REWARD_ENABLED는false로 유지합니다. - 공격력 조정: 일반 역할 피해량은
src/constants.js의FIGHTER_TYPE_STATS.<type>.damageMin/damageMax를 수정하고, elite 추가 공격력은FIGHTER.ELITE.ATTACK_DAMAGE_BONUS_MULTIPLIER와ATTACK_DAMAGE_STACK_EXPONENT를 수정합니다. - 월드 이펙트 및 서든 데스 조정:
src/constants.js의WORLD_EFFECT.METEOR_DAMAGE와WORLD_EFFECT.FROST_DAMAGE는 normal 고정 피해를,METEOR_DAMAGE_PERCENT와FROST_DAMAGE_PERCENT는 elite 최대 체력 비례 피해를 조정합니다.SUDDEN_DEATH.ENABLED로 서든 데스 활성화 여부를 결정하며,TRIGGER_MS(시작 시간),INTERVAL_MS(주기),FORCE_FROST(냉기 고정) 설정을 변경할 수 있습니다.INTERVAL은 첫 포격까지의 대기 시간,REPEAT_INTERVAL은 이후 일반 포격 주기입니다.AREA_TILES는 밀집도를 검색하고 경고로 표시할 큰 구역이며,WARNING_DURATION_MS는 그 경고 표시 시간입니다.IMPACT_AREA_TILES,IMPACT_COUNT_MIN/IMPACT_COUNT_MAX,IMPACT_STAGGER_MS,IMPACT_VISUAL_SCALE는 내부 소형 포격의 판정 범위, 발수, 간격, 시각 크기를 조정합니다.WORLD_EFFECT.FROST_STUN_DURATION/FROST_STUN_TINT로 동결 시간과 표시 색상을 조정합니다.- 나머지
WORLD_EFFECT.*값으로 발동 주기, 범위, 냉각 지속시간과 감속 정도를 수정하며, 메테오 착탄 위치 포커싱은CAMERA.METEOR_FOCUS_ENABLED에서 켜고 끕니다.
- 특수 규칙: 캐릭터별 특수 공격 방식은
fighterManifest.js의combat설정을 확인합니다.