var triggerData = null; var triggerID = null; var triggerKind = ''; function initTriggerEditor() { editorType = 'triggers'; editorFields = []; loadTriggerList(); if (window.location.hash) loadTriggerItem(window.location.hash.substring(1)); } function loadTriggerList() { API.get('/api/triggers').then(function(data) { allIDs = (data || []).map(function(e) { return e.id || e; }); window._triggerEntries = data || []; renderTriggerList(''); }).catch(function(e) { notify('Failed to load list: ' + e.message, 'error'); }); } function renderTriggerList(filter) { var el = $('#listEntries'); var f = (filter || '').toLowerCase(); var entries = window._triggerEntries || []; var html = ''; entries.forEach(function(entry) { var id = entry.id || entry; if (f && id.toLowerCase().indexOf(f) === -1) return; var badge = entry.kind === 'player' ? ' [Player]' : (entry.kind === 'global' ? ' [Global]' : ''); var badgeClass = entry.kind === 'player' ? 'dc-item' : (entry.kind === 'global' ? 'dc-item' : ''); html += '
'; html += '' + esc(id) + ''; html += '' + esc(badge) + ''; html += '
'; }); el.innerHTML = html || '

No triggers

'; } function loadTriggerItem(id) { loadTrigger(id); } function loadTrigger(id) { triggerID = id; currentID = id; window.location.hash = id; renderTriggerList(''); API.get('/api/triggers/' + encodeURIComponent(id)).then(function(data) { triggerData = data; triggerKind = data._kind || ''; if (!Array.isArray(triggerData.steps)) triggerData.steps = []; window._editorData = triggerData; window._ieRenderCurrent = renderCurrent; window._ieRenderOnly = function() { if (triggerID && triggerData) renderTriggerEditor(triggerID, triggerData); }; window._ieSyncAll = function(ed) { if (ed) syncCondDOM(ed); }; renderTriggerEditor(id, data); }).catch(function(e) { $('#editorMain').innerHTML = '

Failed to load: ' + esc(e.message) + '

'; }); } function syncCondDOM(ed) { if (!ed) return; var condRoot = document.querySelector('.obj-card[data-card="condition"] .ie-cond-root'); if (condRoot) { var cond = ie_collectCond(condRoot); if (cond) ed.condition = cond; else delete ed.condition; } } function renderCurrent() { if (!triggerData || !triggerID) return; syncCondDOM(triggerData); var flagTypeEl = document.querySelector('input[name="trigFlagType"]:checked'); if (flagTypeEl) { delete triggerData.on_player_flag; delete triggerData.on_global_flag; if (flagTypeEl.value === 'player') { var n = $('#trigFlagName'); triggerData.on_player_flag = n ? n.value.trim() : ''; } else { var n = $('#trigFlagName'); triggerData.on_global_flag = n ? n.value.trim() : ''; } } var valEl = $('#trigValue'); if (valEl) { var v = valEl.value.trim(); if (v === '') delete triggerData.value; else { try { triggerData.value = JSON.parse(v); } catch(e) { triggerData.value = v; } } } var lockEl = $('#trigLock'); if (lockEl) { if (lockEl.checked) triggerData.lock = true; else delete triggerData.lock; } var stepRows = document.querySelectorAll('.obj-card[data-card="steps"] .ie-step-row'); if (!Array.isArray(triggerData.steps)) triggerData.steps = []; stepRows.forEach(function(stepRow) { var si = parseInt(stepRow.getAttribute('data-step'), 10); if (isNaN(si)) return; if (!triggerData.steps[si]) triggerData.steps[si] = {}; var waitEl = stepRow.querySelector('.wait-input'); if (waitEl) triggerData.steps[si].wait = parseInt(waitEl.value) || 0; syncStepEffects(stepRow, si); }); if (triggerData.steps.length > stepRows.length) triggerData.steps.length = stepRows.length; renderTriggerEditor(triggerID, triggerData); } function syncStepEffects(row, si) { var effectsEl = row.querySelector('.ie-act-root'); if (!effectsEl) return; var step = triggerData.steps[si] || {}; ['messages','broadcast','broadcast_global','teleport','heal','credits', 'give_item','take_item','despawn_mob','aps_node','drop_table'].forEach(function(k) { delete step[k]; }); delete step.set_global_flags; delete step.set_player_flags; delete step.spawn_mob; var msgInputs = effectsEl.querySelectorAll('.trig-msg-input'); var msgs = []; msgInputs.forEach(function(inp) { if (inp.value !== '') msgs.push(inp.value); }); if (msgs.length > 0) step.messages = msgs; effectsEl.querySelectorAll('.trig-effect-input').forEach(function(inp) { var key = inp.getAttribute('data-key'); var v = inp.value.trim(); if (v !== '') { if (key === 'teleport' || key === 'heal' || key === 'credits') step[key] = parseInt(v)||0; else step[key] = v; } }); var cb = effectsEl.querySelector('.trig-aps-cb'); if (cb && cb.checked) step.aps_node = true; effectsEl.querySelectorAll('.trig-kv-section').forEach(function(kvSec) { var kvKey = kvSec.getAttribute('data-kv'); var kvObj = {}; kvSec.querySelectorAll('.trig-kv-row').forEach(function(kvRow) { var kEl = kvRow.querySelector('.trig-kv-key'); var vEl = kvRow.querySelector('.trig-kv-val'); if (kEl && kEl.value) { var v = vEl ? vEl.value : ''; try { kvObj[kEl.value] = JSON.parse(v); } catch(e) { kvObj[kEl.value] = v; } } }); if (Object.keys(kvObj).length > 0) step[kvKey] = kvObj; }); var smInput = effectsEl.querySelector('.trig-spawn-mob'); if (smInput && smInput.value.trim()) { if (!step.spawn_mob) step.spawn_mob = {}; step.spawn_mob.id = smInput.value.trim(); } var dtBlock = effectsEl.querySelector('.ie-drop-table'); if (dtBlock) { var dt = ie_collectDropTableBlock(dtBlock); if (dt) step.drop_table = dt; } triggerData.steps[si] = step; } function renderTriggerEditor(id, data) { var html = renderRenameableHeader('Trigger', id); var kindLabel = data._kind === 'global' ? 'Global Flag' : (data._kind === 'player' ? 'Player Flag' : ''); if (kindLabel) html += '
' + esc(kindLabel) + ' Trigger
'; html += '
'; html += '
'; html += '
'; var isPlayerFlag = data.on_player_flag !== undefined; var isGlobalFlag = data.on_global_flag !== undefined; if (!isPlayerFlag && !isGlobalFlag) isPlayerFlag = true; var flagName = isPlayerFlag ? (data.on_player_flag || '') : (data.on_global_flag || ''); html += '
'; html += '
'; html += 'Flag Subscription'; html += '
'; html += '
'; html += '
'; html += '
'; html += 'Flag Type'; html += '
'; html += ''; html += ''; html += '
'; html += '
'; html += '
'; html += 'Flag Name'; html += ''; html += '
'; html += '
'; html += 'Value (optional)'; html += ''; html += '
'; html += '
'; html += ''; html += 'Lock Player (atomic sequence)'; html += '
'; html += '
'; html += '
'; html += '
'; html += '
'; html += '
'; html += 'Entry Condition'; html += '
'; html += '
'; html += '
' + ie_renderCond(data.condition || null, 'condition', 0, '', 'entry') + '
'; html += '
'; html += '
'; var steps = Array.isArray(data.steps) ? data.steps : []; html += '
'; html += '
'; html += 'Steps (' + steps.length + ')'; html += '
'; html += '
'; html += renderSteps(steps); html += ''; html += '
'; html += '
'; html += '
'; html += ''; html += '
'; html += ''; html += ''; html += '
'; $('#editorMain').innerHTML = html; ced_setupSearchFields(); } function renderSteps(steps) { var h = ''; (steps || []).forEach(function(step, si) { h += '
'; h += '
'; h += 'Step ' + (si + 1) + ''; h += 'Wait:'; h += ''; if (si > 0) h += ''; if (si < steps.length - 1) h += ''; h += ''; h += ''; h += '
'; h += '
'; h += '
'; h += renderStepEffects(step, si); h += '
'; h += '
'; h += '
'; IE_STEP_KINDS.forEach(function(sk) { h += ''; }); h += '
'; h += '
'; }); return h; } function renderStepEffects(step, si) { var h = ''; var msgs = Array.isArray(step.messages) ? step.messages : []; msgs.forEach(function(msg, mi) { h += '
'; h += 'Message'; h += ''; h += '
'; }); if (step.broadcast !== undefined) { h += '
Broadcast'; h += '
'; } if (step.broadcast_global !== undefined) { h += '
Broadcast Global'; h += '
'; } if (step.teleport !== undefined) { h += '
Teleport'; h += '
'; } if (step.heal !== undefined) { h += '
Heal'; h += '
'; } if (step.credits !== undefined) { h += '
Credits'; h += '
'; } if (step.spawn_mob && step.spawn_mob.id) { h += '
Spawn Mob'; h += '
'; } if (step.despawn_mob !== undefined) { h += '
Despawn Mob'; h += '
'; } if (step.give_item !== undefined) { h += '
Give Item'; h += '
'; } if (step.take_item !== undefined) { h += '
Take Item'; h += '
'; } if (step.aps_node) { h += '
APS Node'; h += '
'; } function renderKVSection(label, key, obj) { var h2 = '
'; h2 += '
' + label + '
'; h2 += '
'; Object.keys(obj).forEach(function(k) { h2 += '
'; h2 += ''; h2 += '='; h2 += ''; h2 += '
'; }); h2 += '
'; return h2; } if (step.set_global_flags && typeof step.set_global_flags === 'object' && Object.keys(step.set_global_flags).length > 0) { h += renderKVSection('Set Global Flags', 'set_global_flags', step.set_global_flags); } if (step.set_player_flags && typeof step.set_player_flags === 'object' && Object.keys(step.set_player_flags).length > 0) { h += renderKVSection('Set Player Flags', 'set_player_flags', step.set_player_flags); } if (Array.isArray(step.drop_table) || step.drop_table !== undefined) { h += '
Drop Table
'; h += ie_renderDropTableBlock(step.drop_table, 'trigAddDropRow('+si+',\'item\')', 'trigAddDropRow('+si+',\'table\')', 'trigRemoveDropRow('+si+',__RI__)'); h += '
'; } return h; } function trigAddDropRow(si, kind) { if (!triggerData || !Array.isArray(triggerData.steps) || !triggerData.steps[si]) return; syncAllStepEffects(); var step = triggerData.steps[si]; if (!Array.isArray(step.drop_table)) step.drop_table = []; if (kind === 'table') { step.drop_table.push({table: '', weight: 10, quantity: 1, _kind: 'table'}); } else { step.drop_table.push({item_id: '', weight: 10, quantity: 1, _kind: 'item'}); } renderCurrent(); } function trigRemoveDropRow(si, ri) { if (!triggerData || !Array.isArray(triggerData.steps) || !triggerData.steps[si]) return; syncAllStepEffects(); var step = triggerData.steps[si]; if (!Array.isArray(step.drop_table)) return; step.drop_table.splice(ri, 1); renderCurrent(); } function addStep() { if (!triggerData) return; if (!Array.isArray(triggerData.steps)) triggerData.steps = []; triggerData.steps.push({wait: 0}); renderCurrent(); } function removeStep(si) { if (!triggerData || !Array.isArray(triggerData.steps)) return; triggerData.steps.splice(si, 1); renderCurrent(); } function moveStep(from, to) { if (!triggerData || !Array.isArray(triggerData.steps)) return; var s = triggerData.steps[from]; triggerData.steps.splice(from, 1); triggerData.steps.splice(to, 0, s); renderCurrent(); } function addStepEffect(si, kind) { if (!triggerData) return; syncCondDOM(triggerData); syncAllStepEffects(); if (!Array.isArray(triggerData.steps)) triggerData.steps = []; if (!triggerData.steps[si]) triggerData.steps[si] = {}; var step = triggerData.steps[si]; if (kind === 'messages') { if (!Array.isArray(step.messages)) step.messages = []; step.messages.push(''); } else if (kind === 'wait') { step.wait = (step.wait || 0) + 1; } else { var at = IE_ACT_TYPES.find(function(a) { return a.key === kind; }); if (!at) return; if (at.kind === 'kv') step[kind] = {}; else if (at.kind === 'checkbox') step[kind] = true; else if (at.kind === 'droptable') step[kind] = []; else if (at.kind === 'number') step[kind] = 0; else if (at.kind === 'search') step[kind] = ''; else step[kind] = ''; } renderCurrent(); } function syncAllStepEffects() { var stepRows = document.querySelectorAll('.obj-card[data-card="steps"] .ie-step-row'); if (!Array.isArray(triggerData.steps)) triggerData.steps = []; stepRows.forEach(function(stepRow) { var si = parseInt(stepRow.getAttribute('data-step'), 10); if (isNaN(si)) return; if (!triggerData.steps[si]) triggerData.steps[si] = {}; var waitEl = stepRow.querySelector('.wait-input'); if (waitEl) triggerData.steps[si].wait = parseInt(waitEl.value) || 0; syncStepEffects(stepRow, si); }); } function saveTrigger() { syncCondDOM(triggerData); syncAllStepEffects(); if (!triggerData || !triggerID) return; var flagTypeEl = document.querySelector('input[name="trigFlagType"]:checked'); if (flagTypeEl) { delete triggerData.on_player_flag; delete triggerData.on_global_flag; var n = $('#trigFlagName'); if (flagTypeEl.value === 'player') triggerData.on_player_flag = n ? n.value.trim() : ''; else triggerData.on_global_flag = n ? n.value.trim() : ''; } var valEl = $('#trigValue'); if (valEl) { var v = valEl.value.trim(); if (v === '') delete triggerData.value; else { try { triggerData.value = JSON.parse(v); } catch(e) { triggerData.value = v; } } } var lockEl = $('#trigLock'); if (lockEl) { if (lockEl.checked) triggerData.lock = true; else delete triggerData.lock; } var out = JSON.parse(JSON.stringify(triggerData)); delete out.id; delete out._path; delete out._raw; delete out._kind; ced_cleanOutput(out); API.put('/api/triggers/' + encodeURIComponent(triggerID), out).then(function(resp) { notify('Trigger ' + triggerID + ' saved', 'success'); updateUndoBar(); if (resp) { if (resp._raw) triggerData._raw = resp._raw; if (resp.kind) triggerKind = resp.kind; } loadTriggerList(); }).catch(function(e) { notify('Save failed: ' + e.message, 'error'); }); } function deleteTrigger() { if (!confirm('Delete trigger "' + triggerID + '"?')) return; API.del('/api/triggers/' + encodeURIComponent(triggerID)).then(function() { notify('Trigger ' + triggerID + ' deleted', 'success'); updateUndoBar(); triggerID = null; currentID = null; triggerData = null; triggerKind = ''; $('#editorMain').innerHTML = '

Deleted

'; loadTriggerList(); }).catch(function(e) { notify('Delete failed: ' + e.message, 'error'); }); } function createNew() { var baseID = prompt('Trigger ID (filename without .yaml):'); if (!baseID || !baseID.trim()) return; var id = baseID.trim(); API.post('/api/triggers', {id: id, on_player_flag: '', steps: []}).then(function(resp) { notify('Trigger ' + id + ' created', 'success'); updateUndoBar(); loadTriggerList(); loadTrigger(id); }).catch(function(e) { notify('Create failed: ' + e.message, 'error'); }); }