diff options
Diffstat (limited to 'internal')
| -rw-r--r-- | internal/admin/api_rooms.go | 12 | ||||
| -rw-r--r-- | internal/admin/static/admin.css | 4 | ||||
| -rw-r--r-- | internal/admin/static/colorpicker.js | 7 | ||||
| -rw-r--r-- | internal/admin/static/itemeditor.js | 84 | ||||
| -rw-r--r-- | internal/admin/static/map.js | 40 | ||||
| -rw-r--r-- | internal/admin/static/objecteditor.js | 47 | ||||
| -rw-r--r-- | internal/admin/undo.go | 2 | ||||
| -rw-r--r-- | internal/behavior/behavior.go | 2 | ||||
| -rw-r--r-- | internal/behavior/types.go | 10 | ||||
| -rw-r--r-- | internal/game/act.go | 2 | ||||
| -rw-r--r-- | internal/game/act_clean.go | 2 | ||||
| -rw-r--r-- | internal/game/act_combine.go | 4 | ||||
| -rw-r--r-- | internal/game/act_fletch.go | 12 | ||||
| -rw-r--r-- | internal/game/act_use.go | 4 | ||||
| -rw-r--r-- | internal/game/cmd_clean.go | 4 | ||||
| -rw-r--r-- | internal/game/cmd_craft.go | 2 | ||||
| -rw-r--r-- | internal/game/cmd_smelt.go | 2 | ||||
| -rw-r--r-- | internal/game/cmd_trigger_utility.go | 2 | ||||
| -rw-r--r-- | internal/game/cmd_use.go | 6 | ||||
| -rw-r--r-- | internal/game/core_production.go | 2 | ||||
| -rw-r--r-- | internal/game/production_engine.go | 16 | ||||
| -rw-r--r-- | internal/item/item.go | 2 |
22 files changed, 205 insertions, 63 deletions
diff --git a/internal/admin/api_rooms.go b/internal/admin/api_rooms.go index f615d9d..76bb11c 100644 --- a/internal/admin/api_rooms.go +++ b/internal/admin/api_rooms.go @@ -78,6 +78,8 @@ func (s *AdminServer) handleRooms(w http.ResponseWriter, r *http.Request) { m["exits"] = exits } + var extraFiles []ExtraFile + if linkFrom != nil && linkDir != nil && *linkDir != "" { dir := world.ExitDir(strings.ToLower(*linkDir)) if opp, ok := world.OppositeExit[dir]; ok { @@ -99,11 +101,10 @@ func (s *AdminServer) handleRooms(w http.ResponseWriter, r *http.Request) { writeJSON(w, map[string]any{"error": fmt.Sprintf("write source room: %v", writeErr)}) return } - s.undoStack.Push(ChangeDesc{ - Description: fmt.Sprintf("update room %d (add exit %s to %d)", *linkFrom, *linkDir, id), - FilePath: srcPath, - OldContent: oldContent, - NewContent: newContent, + extraFiles = append(extraFiles, ExtraFile{ + FilePath: srcPath, + OldContent: oldContent, + NewContent: newContent, }) } @@ -124,6 +125,7 @@ func (s *AdminServer) handleRooms(w http.ResponseWriter, r *http.Request) { FilePath: path, NewContent: newContent, IsCreate: true, + ExtraFiles: extraFiles, }) writeJSON(w, map[string]any{"room": m}) diff --git a/internal/admin/static/admin.css b/internal/admin/static/admin.css index bdf9b60..93c1924 100644 --- a/internal/admin/static/admin.css +++ b/internal/admin/static/admin.css @@ -148,7 +148,7 @@ g.ud-hover:hover text{font-weight:bold} .panel-tab-content .search-input{width:100%;padding:4px 6px;font-size:11px;background:var(--input-bg);color:var(--text);border:1px solid var(--input-border);border-radius:3px;font-family:monospace} .panel-tab-content .search-results{position:absolute;top:100%;left:0;right:0;max-height:160px;overflow-y:auto;background:var(--panel);border:1px solid var(--border);border-radius:3px;z-index:50;box-shadow:0 4px 12px rgba(0,0,0,.4)} .panel-tab-content .search-results .sr-item{padding:4px 8px;font-size:11px;cursor:pointer;color:var(--text);border-bottom:1px solid rgba(255,255,255,.03)} -.panel-tab-content .search-results .sr-item:hover{background:var(--accent)} +.panel-tab-content .search-results .sr-item:hover,.panel-tab-content .search-results .sr-item.active{background:var(--accent)} .panel-tab-content .section-add-btn{display:block;width:100%;margin-top:4px;background:var(--accent);color:var(--text);border:1px solid #1a5a8e;padding:4px 8px;font-size:11px;border-radius:3px;cursor:pointer;font-family:monospace} .panel-tab-content .section-add-btn:hover{background:var(--hover)} .panel-tab-content .mini-label{font-size:9px;color:#888;display:block;margin-bottom:1px;margin-top:3px} @@ -201,7 +201,7 @@ g.ud-hover:hover text{font-weight:bold} .obj-search{position:relative!important} .obj-search .search-results{position:absolute;top:100%;left:0;right:0;max-height:160px;overflow-y:auto;background:var(--panel);border:1px solid var(--border);border-radius:3px;z-index:50;box-shadow:0 4px 12px rgba(0,0,0,.4);margin-top:2px} .obj-search .search-results .sr-item{padding:4px 8px;font-size:11px;cursor:pointer;color:var(--text);border-bottom:1px solid rgba(255,255,255,.03)} -.obj-search .search-results .sr-item:hover{background:var(--accent)} +.obj-search .search-results .sr-item:hover,.obj-search .search-results .sr-item.active{background:var(--accent)} .obj-search input.search-input{padding-right:24px;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23888' stroke-width='2'%3E%3Ccircle cx='11' cy='11' r='8'/%3E%3Cpath d='m21 21-4.3-4.3'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 6px center} .obj-search input.search-input::placeholder{color:#666} .obj-narrow.obj-search input{width:80px} diff --git a/internal/admin/static/colorpicker.js b/internal/admin/static/colorpicker.js index 9431e83..bba438e 100644 --- a/internal/admin/static/colorpicker.js +++ b/internal/admin/static/colorpicker.js @@ -62,6 +62,7 @@ window.cssToXtermIdx = function(css) { (function() { var pickerEl = null, boundInput = null, boundSwatch = null; + window._colorPickerActive = false; function ensurePicker() { if (pickerEl) return; @@ -114,6 +115,7 @@ window.cssToXtermIdx = function(css) { idx = parseInt(raw, 16) || 0; } var hex = xtermIdxToHex(idx); + window._colorPickerActive = true; inputEl.value = hex; if (swatchEl) swatchEl.style.background = xtermToCss(idx); @@ -153,7 +155,12 @@ window.cssToXtermIdx = function(css) { window.hideColorPicker = hidePicker; function hidePicker() { if (pickerEl) pickerEl.style.display = 'none'; + var input = boundInput; boundInput = null; boundSwatch = null; + window._colorPickerActive = false; + if (input && input.isConnected) { + input.dispatchEvent(new Event('input', {bubbles:true})); + } } document.addEventListener('click', function(e) { diff --git a/internal/admin/static/itemeditor.js b/internal/admin/static/itemeditor.js index d02945a..7c7c676 100644 --- a/internal/admin/static/itemeditor.js +++ b/internal/admin/static/itemeditor.js @@ -48,10 +48,10 @@ var SECTIONS = [ label: 'Recipes to Craft This Item', key: 'craft', fields: [ ['type', 'Type', 'select', 'smithing|cooking|crafting|fletching|combine|pharmacy|construction'], - ['subtype', 'Subtype', 'select', '|smelt|clean'], + ['subtype', 'Subtype', 'select', '|smelting|cleaning'], ['level', 'Level', 'number', '', 'narrow'], ['xp', 'XP', 'number', '', 'narrow'], - ['wait', 'Wait', 'number', '', 'narrow'], + ['ticks_per_cycle', 'Ticks/Cycle', 'number', '', 'narrow'], ['output_qty', 'Output Qty', 'number', '', 'narrow'], ['station', 'Station', 'select', '|anvil|cooking_range|fire|furnace|pottery_oven|pottery_wheel|spinning_wheel|workbench'], ['tool', 'Tool', 'select', '|pickaxe|axe|fire|chisel|hammer|knife|needle|rake|saw|shears|spade|watering_can|fishing_rod|fly_rod|harpoon|small_net|big_net|lobster_pot'], @@ -65,8 +65,9 @@ var SECTIONS = [ ['end_message', 'End Message', 'text', 'e.g. You\'ve finished smithing.', 'wide'], ], fieldGroups: [ - ['type', 'subtype', 'level', 'xp', 'wait', 'output_qty'], - {fields: ['station', 'tool'], right: true}, + ['type', 'subtype', 'level', 'xp', 'ticks_per_cycle', 'output_qty'], + {note: 'Output Qty is the quantity produced per cycle, only relevant for stackable items.'}, + ['station', 'tool'], {label: 'Success', fields: ['success_base', 'success_per_level', 'success_cap', 'fail']}, ['start_message', 'success_message', 'fail_message', 'end_message'], ], @@ -213,6 +214,7 @@ function renderItemEditor(id, data) { $('#editorMain').innerHTML = html; setupSearchFields(); setupCraftTypeChange(); + updateOutputQtyVisibility(); setTimeout(function() { document.querySelectorAll('.color-field').forEach(function(el) { bindColorField(el); }); }, 50); @@ -229,7 +231,7 @@ function renderCurrent() { function renderCard(sec, data) { var collapsed = expandedCards[sec.id] === false; - var h = '<div class="obj-card' + (sec.id === 'crafting' ? ' obj-card-full' : '') + '" data-card="' + sec.id + '">'; + var h = '<div class="obj-card" data-card="' + sec.id + '">'; h += '<div class="obj-card-header" onclick="toggleCard(\'' + sec.id + '\')">'; h += '<span class="obj-card-arrow">' + (collapsed ? '▶' : '▼') + '</span>'; h += '<span class="obj-card-label">' + sec.label + '</span>'; @@ -600,6 +602,10 @@ function renderSubtable(sec, st, data) { function renderGroup(fieldKeys) { fieldKeys.forEach(function(fieldKey) { + if (fieldKey === '|') { + h += '<span class="craft-sep" style="color:#555;margin:0 4px;font-size:14px;line-height:1;align-self:center">|</span>'; + return; + } var f = st.fields.find(function(sf) { return sf[0] === fieldKey; }); if (!f) return; if (f[5] && !f[5](item)) return; @@ -610,9 +616,11 @@ function renderSubtable(sec, st, data) { if (st.fieldGroups) { st.fieldGroups.forEach(function(group) { - if (group.label) { + if (group.note) { + h += '<div class="obj-field-note output-qty-note" style="margin:2px 0;padding:2px 8px;font-size:11px;color:#888;font-style:italic;line-height:1.3">' + esc(group.note) + '</div>'; + } else if (group.label) { if (group.label === 'Success') { - var hasSuccess = !!(item.fail || item.success_base || item.success_per_level || item.success_cap); + var hasSuccess = !!(item.fail || (item.success && (item.success.base || item.success.per_level || item.success.cap)) || item.success_base || item.success_per_level || item.success_cap); var gid = 'sg_' + sec.id + '_' + st.key + '_' + idx; h += '<div class="obj-inline-group success-group" id="' + gid + '" style="margin:2px 0;padding:4px 8px' + (hasSuccess ? '' : ';display:none') + '">'; h += '<div style="display:flex;align-items:center;margin-bottom:2px">'; @@ -1039,7 +1047,7 @@ function setupCraftTypeChange() { var xpField = document.getElementById(id.replace(/_type$/, '_xp')); var stationField = document.getElementById(id.replace(/_type$/, '_station')); - var combineHideFields = ['success_message', 'fail_message', 'tool', 'wait', + var combineHideFields = ['success_message', 'fail_message', 'tool', 'ticks_per_cycle', 'success_base', 'success_per_level', 'success_cap', 'fail']; var recipeRow = typeSelect.closest('.obj-sub-row'); @@ -1065,6 +1073,9 @@ function setupCraftTypeChange() { if (lbl) lbl.style.display = t === 'combine' ? 'none' : ''; }); + var sepEl = recipeRow.querySelector('.craft-sep'); + if (sepEl) sepEl.style.display = t === 'combine' ? 'none' : ''; + var successGroup = document.querySelector('.success-group'); if (successGroup) successGroup.style.display = t === 'combine' ? 'none' : ''; var successBtn = document.getElementById(successGroup ? successGroup.id + '_btn' : ''); @@ -1081,10 +1092,10 @@ function setupCraftTypeChange() { var sLbl = subtypeSel.closest('.obj-field'); if (t === 'smithing') { if (sLbl) sLbl.style.display = ''; - subtypeSel.innerHTML = '<option value="">none</option><option value="smelt">smelt</option>'; + subtypeSel.innerHTML = '<option value="">none</option><option value="smelting">smelting</option>'; } else if (t === 'pharmacy') { if (sLbl) sLbl.style.display = ''; - subtypeSel.innerHTML = '<option value="">none</option><option value="clean">clean</option>'; + subtypeSel.innerHTML = '<option value="">none</option><option value="cleaning">cleaning</option>'; } else { if (sLbl) sLbl.style.display = 'none'; subtypeSel.value = ''; @@ -1097,6 +1108,26 @@ function setupCraftTypeChange() { }); } +function updateOutputQtyVisibility() { + var isStackable = false; + var stackableEl = document.getElementById('f_core_stackable'); + if (stackableEl) { + isStackable = stackableEl.checked; + if (!stackableEl._hasOutputQtyListener) { + stackableEl._hasOutputQtyListener = true; + stackableEl.addEventListener('change', updateOutputQtyVisibility); + } + } + + document.querySelectorAll('[id$="_output_qty"]').forEach(function(el) { + var lbl = el.closest('.obj-field'); + if (lbl) lbl.style.display = isStackable ? '' : 'none'; + }); + document.querySelectorAll('.output-qty-note').forEach(function(el) { + el.style.display = isStackable ? '' : 'none'; + }); +} + function setupSearchFields() { document.querySelectorAll('.search-input').forEach(function(input) { if (input._searchSetup) return; @@ -1109,7 +1140,7 @@ function setupSearchFields() { input.addEventListener('input', function() { var val = input.value.trim(); - if (!val) { results.style.display = 'none'; results.innerHTML = ''; return; } + if (!val) { results.style.display = 'none'; results.innerHTML = ''; results._selectedIndex = -1; return; } API.get('/api/search?q=' + encodeURIComponent(val)).then(function(data) { var items = []; if (entityType === 'items' && data.items) items = data.items; @@ -1126,6 +1157,7 @@ function setupSearchFields() { return '<div class="sr-item" onclick="event.stopPropagation();selectSearchResult(this)">' + esc(r.id) + ' <span style="color:#aaa">' + esc(r.name || '') + '</span></div>'; }).join(''); results._items = items; + results._selectedIndex = -1; }).catch(function() { results.style.display = 'none'; }); @@ -1140,6 +1172,29 @@ function setupSearchFields() { input.addEventListener('blur', function() { setTimeout(function() { results.style.display = 'none'; }, 200); }); + + input.addEventListener('keydown', function(e) { + if (results.style.display === 'none' || !results.children.length) return; + if (results._selectedIndex === undefined) results._selectedIndex = -1; + + if (e.key === 'ArrowDown') { + e.preventDefault(); + results._selectedIndex = Math.min(results._selectedIndex + 1, results.children.length - 1); + updateSearchHighlight(results); + } else if (e.key === 'ArrowUp') { + e.preventDefault(); + results._selectedIndex = Math.max(results._selectedIndex - 1, 0); + updateSearchHighlight(results); + } else if (e.key === 'Enter') { + if (results._selectedIndex >= 0) { + e.preventDefault(); + selectSearchResult(results.children[results._selectedIndex]); + } + } else if (e.key === 'Escape') { + results.style.display = 'none'; + results._selectedIndex = -1; + } + }); }); document.addEventListener('click', function(e) { @@ -1160,6 +1215,13 @@ function selectSearchResult(el) { } } +function updateSearchHighlight(results) { + for (var i = 0; i < results.children.length; i++) { + results.children[i].classList.toggle('active', i === results._selectedIndex); + if (i === results._selectedIndex) results.children[i].scrollIntoView({block: 'nearest'}); + } +} + // ========================================================================= // Validation // ========================================================================= diff --git a/internal/admin/static/map.js b/internal/admin/static/map.js index e5d9a19..95bde7e 100644 --- a/internal/admin/static/map.js +++ b/internal/admin/static/map.js @@ -594,8 +594,8 @@ function renderItemsTab(spawns) { spawns.forEach(function(spawn, i) { h += '<div class="entry-row" data-idx="' + i + '">'; h += '<div class="entry-fields">'; - h += '<span class="entry-id">' + esc(spawn.id || '') + '</span>'; h += '<div style="display:flex;gap:8px;align-items:center;">'; + h += '<span class="entry-id" style="flex:1;display:inline;padding:0">' + esc(spawn.id || '') + '</span>'; h += '<div><label class="mini-label">Quantity</label><input class="mini-input spawn-qty" type="text" inputmode="numeric" pattern="[0-9]*" value="' + (spawn.quantity || 0) + '" onchange="updateSpawn(' + i + ')"></div>'; h += '<div><label class="mini-label">Respawn</label><input class="mini-input spawn-respawn" type="text" inputmode="numeric" pattern="[0-9]*" value="' + (spawn.respawn_ticks || 0) + '" onchange="updateSpawn(' + i + ')"></div>'; h += '</div>'; @@ -1066,7 +1066,7 @@ function searchMobs(input) { function searchAndShow(input, type, onSelect) { var val = input.value.trim(); var results = input.parentElement.querySelector('.search-results'); - if (!val) { results.style.display = 'none'; results.innerHTML = ''; return; } + if (!val) { results.style.display = 'none'; results.innerHTML = ''; results._selectedIndex = -1; return; } API.get('/api/search?q=' + encodeURIComponent(val)).then(function(data) { var items = []; if (type === 'objects' && data.objects) items = data.objects; @@ -1084,9 +1084,36 @@ function searchAndShow(input, type, onSelect) { }).join(''); results._items = items; results._onSelect = onSelect; + results._selectedIndex = -1; }).catch(function() { results.style.display = 'none'; }); + + input._searchKeySetup = input._searchKeySetup || (function() { + input.addEventListener('keydown', function(e) { + if (results.style.display === 'none' || !results.children.length) return; + if (results._selectedIndex === undefined) results._selectedIndex = -1; + + if (e.key === 'ArrowDown') { + e.preventDefault(); + results._selectedIndex = Math.min(results._selectedIndex + 1, results.children.length - 1); + updateSearchHighlight(results); + } else if (e.key === 'ArrowUp') { + e.preventDefault(); + results._selectedIndex = Math.max(results._selectedIndex - 1, 0); + updateSearchHighlight(results); + } else if (e.key === 'Enter') { + if (results._selectedIndex >= 0) { + e.preventDefault(); + selectSearchResult(results.children[results._selectedIndex]); + } + } else if (e.key === 'Escape') { + results.style.display = 'none'; + results._selectedIndex = -1; + } + }); + return true; + })(); } function selectSearchResult(el) { @@ -1101,6 +1128,13 @@ function selectSearchResult(el) { } } +function updateSearchHighlight(results) { + for (var i = 0; i < results.children.length; i++) { + results.children[i].classList.toggle('active', i === results._selectedIndex); + if (i === results._selectedIndex) results.children[i].scrollIntoView({block: 'nearest'}); + } +} + function openEditor(type, id) { window.open('/editor/' + type + '#' + id, '_blank'); } @@ -1111,11 +1145,13 @@ function reRenderPanel() { } function autoSave() { + if (window._colorPickerActive) return; if (saveTimer) clearTimeout(saveTimer); saveTimer = setTimeout(function() { doSavePanel(); }, 600); } function saveNow() { + if (window._colorPickerActive) return; if (saveTimer) clearTimeout(saveTimer); saveTimer = null; doSavePanel(); diff --git a/internal/admin/static/objecteditor.js b/internal/admin/static/objecteditor.js index 13a983e..56894d2 100644 --- a/internal/admin/static/objecteditor.js +++ b/internal/admin/static/objecteditor.js @@ -103,7 +103,7 @@ var SECTIONS = [ }, { id: 'use_interactions', label: 'Use Interactions', path: 'use_interactions', isArray: true, - detect: function(d) { return d.use_interactions && d.use_interactions.length; }, + detect: function(d) { return d.use_interactions && Array.isArray(d.use_interactions); }, fields: [ ['item_id', 'Item ID', 'text'], ['message', 'Message', 'text'], @@ -150,6 +150,7 @@ window.onTalkTreeChange = function(data) { function loadObject(id) { objectID = id; + currentID = id; window.location.hash = id; renderList(''); API.get('/api/objects/' + encodeURIComponent(id)).then(function(data) { @@ -577,6 +578,12 @@ function addSection() { } else { objectData[sec.path] = {}; } + } else if (id === 'steal') { + objectData.steal_table = ''; + objectData.steal_level = 0; + objectData.steal_xp = 0; + objectData.steal_speed = 0; + objectData.guard_mob = ''; } expandedCards[id] = true; renderCurrent(); @@ -683,7 +690,7 @@ function setupSearchFields() { input.addEventListener('input', function() { var val = input.value.trim(); - if (!val) { results.style.display = 'none'; results.innerHTML = ''; return; } + if (!val) { results.style.display = 'none'; results.innerHTML = ''; results._selectedIndex = -1; return; } API.get('/api/search?q=' + encodeURIComponent(val)).then(function(data) { var items = []; if (entityType === 'items' && data.items) items = data.items; @@ -700,6 +707,7 @@ function setupSearchFields() { return '<div class="sr-item" onclick="event.stopPropagation();selectObjSearchResult(this)">' + esc(r.id) + ' <span style="color:#aaa">' + esc(r.name || '') + '</span></div>'; }).join(''); results._items = items; + results._selectedIndex = -1; }).catch(function() { results.style.display = 'none'; }); @@ -714,6 +722,29 @@ function setupSearchFields() { input.addEventListener('blur', function() { setTimeout(function() { results.style.display = 'none'; }, 200); }); + + input.addEventListener('keydown', function(e) { + if (results.style.display === 'none' || !results.children.length) return; + if (results._selectedIndex === undefined) results._selectedIndex = -1; + + if (e.key === 'ArrowDown') { + e.preventDefault(); + results._selectedIndex = Math.min(results._selectedIndex + 1, results.children.length - 1); + updateSearchHighlight(results); + } else if (e.key === 'ArrowUp') { + e.preventDefault(); + results._selectedIndex = Math.max(results._selectedIndex - 1, 0); + updateSearchHighlight(results); + } else if (e.key === 'Enter') { + if (results._selectedIndex >= 0) { + e.preventDefault(); + selectObjSearchResult(results.children[results._selectedIndex]); + } + } else if (e.key === 'Escape') { + results.style.display = 'none'; + results._selectedIndex = -1; + } + }); }); document.addEventListener('click', function(e) { @@ -734,6 +765,13 @@ function selectObjSearchResult(el) { } } +function updateSearchHighlight(results) { + for (var i = 0; i < results.children.length; i++) { + results.children[i].classList.toggle('active', i === results._selectedIndex); + if (i === results._selectedIndex) results.children[i].scrollIntoView({block: 'nearest'}); + } +} + function validateFields() { var errors = []; document.querySelectorAll('.obj-field-error').forEach(function(field) { @@ -974,16 +1012,13 @@ function deleteObject() { notify('Object ' + objectID + ' deleted', 'success'); updateUndoBar(); objectID = null; + currentID = null; objectData = null; $('#editorMain').innerHTML = '<p style="color:#888;text-align:center;margin-top:60px">Deleted</p>'; loadList(); }).catch(function(e) { notify('Delete failed: ' + e.message, 'error'); }); } -// Re-exports for editor.js compatibility -var currentID = null; -Object.defineProperty(window, 'currentID', { get: function() { return objectID; }, set: function(v) { objectID = v; } }); - function loadItem(id) { loadObject(id); } function createNew() { var name = prompt('Object ID:'); diff --git a/internal/admin/undo.go b/internal/admin/undo.go index bec3c35..8f75d30 100644 --- a/internal/admin/undo.go +++ b/internal/admin/undo.go @@ -140,7 +140,7 @@ func (us *UndoStack) applyUndo(c ChangeDesc) error { } else if c.IsCreate { os.Remove(c.FilePath) for _, ef := range c.ExtraFiles { - os.Remove(ef.FilePath) + os.WriteFile(ef.FilePath, ef.OldContent, 0644) } } else { target := c.FilePath diff --git a/internal/behavior/behavior.go b/internal/behavior/behavior.go index c0a714c..2ef7fae 100644 --- a/internal/behavior/behavior.go +++ b/internal/behavior/behavior.go @@ -84,7 +84,7 @@ type Condition struct { type UseConfig struct { StartMessage string `yaml:"start_message"` - Wait float64 `yaml:"wait"` + TicksPerCycle float64 `yaml:"ticks_per_cycle"` Consume map[string]int `yaml:"consume"` Reward DropEntry `yaml:"reward"` FailMessage string `yaml:"fail_message"` diff --git a/internal/behavior/types.go b/internal/behavior/types.go index 571f2c4..c59a95e 100644 --- a/internal/behavior/types.go +++ b/internal/behavior/types.go @@ -46,9 +46,9 @@ const ( TypeCure ActionType = "cure" TypeObstacle ActionType = "obstacle" TypeFletch ActionType = "fletch" - TypeClean ActionType = "clean" + TypeClean ActionType = "cleaning" TypeCook ActionType = "cook" - TypeSmelt ActionType = "smelt" + TypeSmelt ActionType = "smelting" TypeSmith ActionType = "smith" TypeCraft ActionType = "craft" TypeCombine ActionType = "combine" @@ -88,7 +88,7 @@ type GatherData struct { type ProductionData struct { ItemID string Phase int - Wait float64 + TicksPerCycle float64 StartMessage string EndMessage string Remaining int @@ -184,13 +184,13 @@ type CombineData struct { Remaining int StartMessage string EndMessage string - Wait float64 + TicksPerCycle float64 } type FletchData struct { ItemID string Phase int - Wait float64 + TicksPerCycle float64 Remaining int } diff --git a/internal/game/act.go b/internal/game/act.go index c8101ab..6d4a208 100644 --- a/internal/game/act.go +++ b/internal/game/act.go @@ -263,7 +263,7 @@ func (g *Game) AdvanceActions() { switch p.BackgroundAction.Type { case "fletch": g.advanceFletch(sess, p) - case "clean": + case "cleaning": g.advanceClean(sess, p) } if p.BackgroundAction == nil { diff --git a/internal/game/act_clean.go b/internal/game/act_clean.go index 7647f4f..f5f86d6 100644 --- a/internal/game/act_clean.go +++ b/internal/game/act_clean.go @@ -25,7 +25,7 @@ func (g *Game) advanceClean(sess *net.Session, p *player.Player) { return } - items := g.CraftIndex.BySubtype("clean") + items := g.CraftIndex.BySubtype("cleaning") var matchItem *item.ItemDef for _, item := range items { diff --git a/internal/game/act_combine.go b/internal/game/act_combine.go index 8937d38..db7fee1 100644 --- a/internal/game/act_combine.go +++ b/internal/game/act_combine.go @@ -38,7 +38,7 @@ func (g *Game) startCombine(sess *net.Session, p *player.Player, item *item.Item Remaining: count, StartMessage: startMsg, EndMessage: endMsg, - Wait: craft.Wait, + TicksPerCycle: craft.TicksPerCycle, }, WaitLeft: engine.ToTicks(1), } @@ -69,7 +69,7 @@ func (g *Game) advanceCombine(sess *net.Session, p *player.Player) { if len(craft.Steps) > 0 { p.Action.WaitLeft = engine.ToTicks(craft.Steps[0].Delay) } else { - firstWait := craft.Wait + firstWait := craft.TicksPerCycle if firstWait <= 0 { firstWait = 4 } diff --git a/internal/game/act_fletch.go b/internal/game/act_fletch.go index ce3a525..c4dcef0 100644 --- a/internal/game/act_fletch.go +++ b/internal/game/act_fletch.go @@ -15,7 +15,7 @@ func (g *Game) startFletchAction(sess *net.Session, p *player.Player, def *item. g.setPlayerFlag(p, "last_fletch", def.ID) g.AccountStore.SaveCharacter(p) - if def.FirstCraft().Wait <= 0 { + if def.FirstCraft().TicksPerCycle <= 0 { g.doInstantFletch(sess, p, def, count) return } @@ -113,10 +113,10 @@ func (g *Game) startTimedFletch(sess *net.Session, p *player.Player, def *item.I TargetID: def.ID, TargetName: def.Name, Data: &behavior.FletchData{ - ItemID: def.ID, - Phase: 0, - Wait: craft.Wait, - Remaining: count, + ItemID: def.ID, + Phase: 0, + TicksPerCycle: craft.TicksPerCycle, + Remaining: count, }, WaitLeft: engine.ToTicks(1), } @@ -130,7 +130,7 @@ func (g *Game) advanceFletch(sess *net.Session, p *player.Player) { } itemID := data.ItemID phase := data.Phase - wait := data.Wait + wait := data.TicksPerCycle remaining := data.Remaining def := g.loadCraftItem(itemID) diff --git a/internal/game/act_use.go b/internal/game/act_use.go index 1e9d8e9..46ca304 100644 --- a/internal/game/act_use.go +++ b/internal/game/act_use.go @@ -84,7 +84,7 @@ func (g *Game) advanceUse(sess *net.Session, p *player.Player) { if cfg.FailMessage != "" { sess.WriteLine(cfg.FailMessage) } - p.Action.WaitLeft = engine.ToTicks(cfg.Wait) + p.Action.WaitLeft = engine.ToTicks(cfg.TicksPerCycle) return } } @@ -137,5 +137,5 @@ func (g *Game) advanceUse(sess *net.Session, p *player.Player) { sess.WriteLine(cfg.EndMessage) } - p.Action.WaitLeft = engine.ToTicks(cfg.Wait) + p.Action.WaitLeft = engine.ToTicks(cfg.TicksPerCycle) } diff --git a/internal/game/cmd_clean.go b/internal/game/cmd_clean.go index f77ff57..9fc37b7 100644 --- a/internal/game/cmd_clean.go +++ b/internal/game/cmd_clean.go @@ -22,7 +22,7 @@ func (g *Game) doClean(sess *net.Session, input string) { return } - items := g.CraftIndex.BySubtype("clean") + items := g.CraftIndex.BySubtype("cleaning") filter := strings.TrimSpace(input) @@ -63,7 +63,7 @@ func (g *Game) doClean(sess *net.Session, input string) { g.cancelBgAction(p) p.BackgroundAction = &behavior.Action{ - Type: "clean", + Type: "cleaning", TargetID: "clean_herbs", Data: &behavior.CleanData{ Phase: 0, diff --git a/internal/game/cmd_craft.go b/internal/game/cmd_craft.go index 3d23f85..37038c0 100644 --- a/internal/game/cmd_craft.go +++ b/internal/game/cmd_craft.go @@ -171,7 +171,7 @@ func (g *Game) startItem(sess *net.Session, p *player.Player, def *item.ItemDef, } func (g *Game) hasGrimyHerbs(p *player.Player) bool { - items := g.CraftIndex.BySubtype("clean") + items := g.CraftIndex.BySubtype("cleaning") for _, def := range items { if def.FindCraft(func(c item.CraftDef) bool { return craftHasAllItems(&c, p.HasItem) diff --git a/internal/game/cmd_smelt.go b/internal/game/cmd_smelt.go index b551e76..4500c64 100644 --- a/internal/game/cmd_smelt.go +++ b/internal/game/cmd_smelt.go @@ -23,7 +23,7 @@ func (g *Game) doSmelt(sess *net.Session, input string) { return } - items := g.CraftIndex.BySubtype("smelt") + items := g.CraftIndex.BySubtype("smelting") if input == "" { g.showSmeltMenu(sess, p, items, stationDefID, stationName) diff --git a/internal/game/cmd_trigger_utility.go b/internal/game/cmd_trigger_utility.go index 1697417..5a4dcc7 100644 --- a/internal/game/cmd_trigger_utility.go +++ b/internal/game/cmd_trigger_utility.go @@ -170,7 +170,7 @@ func (g *Game) triggerSuperheat(sess *net.Session, p *player.Player, mod *ModDef } var match *item.ItemDef - for _, item := range g.CraftIndex.BySubtype("smelt") { + for _, item := range g.CraftIndex.BySubtype("smelting") { if craftMatchesEntry(item.FirstCraft(), inv.ItemID) { match = item break diff --git a/internal/game/cmd_use.go b/internal/game/cmd_use.go index 1989a3e..72de3d6 100644 --- a/internal/game/cmd_use.go +++ b/internal/game/cmd_use.go @@ -225,11 +225,11 @@ func (g *Game) doUseItemOnTarget(sess *net.Session, p *player.Player, itemAName, if len(recipes[0].Craft) > 0 { firstSubtype = recipes[0].FirstCraft().Subtype } - if firstSubtype == "smelt" { + if firstSubtype == "smelting" { var filtered []*item.ItemDef for _, item := range recipes { c := item.FirstCraft() - if c.Subtype != "smelt" { + if c.Subtype != "smelting" { continue } if !craftHasAllItemsQty(c, p.CountItem) { @@ -417,7 +417,7 @@ func (g *Game) doUseItemOnTarget(sess *net.Session, p *player.Player, itemAName, } func (g *Game) isGrimyHerb(itemID string) bool { - items := g.CraftIndex.BySubtype("clean") + items := g.CraftIndex.BySubtype("cleaning") for _, item := range items { for _, e := range item.FirstCraft().Ingredients { for _, id := range e.Items { diff --git a/internal/game/core_production.go b/internal/game/core_production.go index e6a62d4..e88f512 100644 --- a/internal/game/core_production.go +++ b/internal/game/core_production.go @@ -58,7 +58,7 @@ var productionTypes = map[string]productionTypeInfo{ EndMessage: "You've finished cooking.", FailMessage: "You accidentally burn the %i1.", }, - "smelt": { + "smelting": { ActionType: behavior.TypeSmelt, DisplayVerb: "smelting", StartMessage: "You place the %i1 into the furnace.", diff --git a/internal/game/production_engine.go b/internal/game/production_engine.go index 1d54714..2fb7968 100644 --- a/internal/game/production_engine.go +++ b/internal/game/production_engine.go @@ -95,7 +95,7 @@ func (g *Game) startProduction(sess *net.Session, p *player.Player, item *item.I outDef, _ := g.ItemStore.Load(item.ID) - wait := craft.Wait + wait := craft.TicksPerCycle if wait <= 0 { wait = 4 } @@ -110,12 +110,12 @@ func (g *Game) startProduction(sess *net.Session, p *player.Player, item *item.I TargetID: item.ID, TargetName: outputName, Data: &behavior.ProductionData{ - ItemID: item.ID, - Phase: 0, - Wait: wait, - StartMessage: startMsg, - EndMessage: endMsg, - Remaining: count, + ItemID: item.ID, + Phase: 0, + TicksPerCycle: wait, + StartMessage: startMsg, + EndMessage: endMsg, + Remaining: count, }, WaitLeft: engine.ToTicks(1), } @@ -181,7 +181,7 @@ func (g *Game) advanceProduction(sess *net.Session, p *player.Player) bool { } itemID := d.ItemID phase := d.Phase - wait := d.Wait + wait := d.TicksPerCycle startMsg := d.StartMessage endMsg := d.EndMessage remaining := d.Remaining diff --git a/internal/item/item.go b/internal/item/item.go index 9c753b1..8edae92 100644 --- a/internal/item/item.go +++ b/internal/item/item.go @@ -280,7 +280,7 @@ type CraftDef struct { Subtype string `yaml:"subtype,omitempty"` Level int `yaml:"level"` XP int `yaml:"xp"` - Wait float64 `yaml:"wait"` + TicksPerCycle float64 `yaml:"ticks_per_cycle"` Station []string `yaml:"station"` Tool string `yaml:"tool"` Ingredients []IngredientEntry `yaml:"ingredients"` |
