Compare commits

..

4 Commits

Author SHA1 Message Date
Akurosia Kamo
4345fadc1c Merge remote-tracking branch 'origin/main' into akus_schabernack4 2026-05-24 08:22:40 +02:00
xziino
669bcd937b Planer: Scroll-Position im Gantt nach Re-Render beibehalten
refreshTimeline() speichert scrollLeft vor dem innerHTML-Reset und
stellt ihn danach wieder her – die Ansicht springt beim Verschieben
von Abilities nicht mehr an den Anfang.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-24 08:21:51 +02:00
xziino
be65d0b228 Planer: Gantt-Overlap-Check auf vollen Cooldown erweitert
assignmentWindowMs und candidateWindow nutzen jetzt max(duration, cooldown)
statt nur die aktive Dauer – Abilities konnten bisher erneut platziert werden
bevor ihr Recast abgelaufen war.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-24 08:17:22 +02:00
xziino
c983ca6621 Planer: Gantt-Klick zum Hinzufügen repariert (Pointer-Capture-Bug)
setPointerCapture() leitet Compatibility Mouse Events (inkl. click) an das
capturing Element um – e.target im click-Handler war immer .timeline-scroll,
nie das angeklickte .timeline-track. Fix: document.elementFromPoint() für
zuverlässigen Hit-Test unabhängig von Pointer Capture.
Pan-Threshold zusätzlich von 3px auf 8px erhöht.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-24 08:12:09 +02:00

View File

@ -836,7 +836,9 @@ function layoutBossActions(mechanics, duration) {
}
function assignmentWindowMs(assignment) {
return Math.max(1, assignmentDurationSeconds(assignment)) * 1000;
const durationMs = Math.max(1, assignmentDurationSeconds(assignment)) * 1000;
const cooldownMs = assignmentCooldownSeconds(assignment) * 1000;
return Math.max(durationMs, cooldownMs);
}
function sameAssignmentRef(mechanic, assignment, ref) {
@ -847,7 +849,9 @@ function sameAssignmentRef(mechanic, assignment, ref) {
}
function assignmentOverlapsJob(plan, job, ability, timestamp, ignore = null, candidate = null) {
const candidateWindow = Math.max(candidate ? assignmentDurationSeconds(candidate) : 0, 1) * 1000;
const candidateDurationMs = Math.max(candidate ? assignmentDurationSeconds(candidate) : 0, 1) * 1000;
const candidateCooldownMs = candidate ? assignmentCooldownSeconds(candidate) * 1000 : 0;
const candidateWindow = Math.max(candidateDurationMs, candidateCooldownMs);
const candidateStart = Math.max(0, timestamp);
const candidateEnd = candidateStart + candidateWindow;
const ignoredActivation = assignmentEntryForRef(plan, ignore);
@ -1034,7 +1038,12 @@ function refreshTimeline(planId) {
if (normalizeActivationCopies(plan)) updatePlan(planId, { mechanics: plan.mechanics });
const timeline = document.getElementById('planner-timeline');
const settings = document.getElementById('timeline-settings');
if (timeline) timeline.innerHTML = renderTimelineHtml(plan);
if (timeline) {
const savedScroll = timeline.querySelector('.timeline-scroll')?.scrollLeft ?? 0;
timeline.innerHTML = renderTimelineHtml(plan);
const newScroll = timeline.querySelector('.timeline-scroll');
if (newScroll && savedScroll > 0) newScroll.scrollLeft = savedScroll;
}
if (settings) settings.innerHTML = renderTimelineSettingsHtml(plan);
}
@ -1242,7 +1251,7 @@ function initTimeline(planId) {
timeline.addEventListener('pointermove', e => {
if (!timelinePan || timelinePan.pointerId !== e.pointerId) return;
const dx = e.clientX - timelinePan.startX;
if (Math.abs(dx) > 3) {
if (Math.abs(dx) > 8) {
timelinePan.moved = true;
timelinePan.scroll.classList.add('timeline-scroll--dragging');
timelinePan.scroll.scrollLeft = timelinePan.startScrollLeft - dx;
@ -1307,8 +1316,11 @@ function initTimeline(planId) {
return;
}
const track = e.target.closest('.timeline-player-row .timeline-track');
const row = e.target.closest('.timeline-player-row');
// setPointerCapture() leitet compatibility mouse events (inkl. click) an das
// capturing element um, daher e.target nicht verlässlich — echtes Element per Hit-Test:
const actualTarget = document.elementFromPoint(e.clientX, e.clientY);
const track = actualTarget?.closest('.timeline-player-row .timeline-track');
const row = actualTarget?.closest('.timeline-player-row');
if (!track || !row) return;
const plan = getPlan(planId);
if (!plan) return;