/* The legend of Zelda: Tears of the Kingdom savegame editor - Pouch class (last update 2023-07-11) by Marc Robledo 2023 item names compiled by Echocolat, Exincracci, HylianLZ and Karlos007 */ function Pouch(catId){ this.category=catId; this.read(); } Pouch.prototype.read=function(){ var categoryItemStructId=Pouch.getCategoryItemStructId(this.category); this.struct=(new Struct(Pouch.getCategoryStructId(this.category), [{ structArray:categoryItemStructId, variablesInfo:Pouch.getCategoryStruct(this.category) }])); var structExported=this.struct.export(); this.items=[]; this.maxSize=structExported[categoryItemStructId].length; for(var i=0; i=this.items.length) return false; var removedItem=this.items[index]; this.items.splice(index,1); return removedItem; } Pouch.prototype.save=function(){ for(var i=0; i this.maxValue) newVal=this.maxValue; if(newVal===-0) newVal=0; //avoid negative zero this.item.lastInputChanged=this.propertyName; if(this.percentage) this.item[this.propertyName]=newVal / 100; else this.item[this.propertyName]=newVal; Pouch.updateItemRow(this.item); } Pouch._onChangeInputTextFix=function(evt){ var newVal=this.value.substr(0, this.maxLength); if(!newVal) newVal='a'; this.item.lastInputChanged=this.propertyName; this.item[this.propertyName]=newVal; Pouch.updateItemRow(this.item); } const ICON_PATH='./assets/item_icons/'; Pouch.updateItemIcon=function(item){ if(item.id==='Parasail'){ var parasailPattern=typeof SavegameEditor.parasailPattern.value==='string'? SavegameEditor.parasailPattern.value : hashReverse(SavegameEditor.parasailPattern.value); if(parasailPattern!=='Default'){ item._htmlIcon.src=ICON_PATH+item.category+'/'+item.id+'_'+parasailPattern+'.png'; }else{ item._htmlIcon.src=ICON_PATH+item.category+'/'+item.id+'.png'; } }else if(item.category==='armors') if(item.dyeColor===hash('None')) item._htmlIcon.src=ICON_PATH+item.category+'/'+item.getBaseId()+'.png'; else item._htmlIcon.src=ICON_PATH+item.category+'/dye/'+item.getBaseId()+'_'+hashReverse(item.dyeColor)+'.png'; else if(item.category==='food' && item.id==='Item_Cook_C_17' && Item.VALID_ELIXIR_EFFECTS.indexOf(hashReverse(item.effect))!==-1) item._htmlIcon.src=ICON_PATH+item.category+'/Item_Cook_C_17_'+hashReverse(item.effect)+'.png'; else item._htmlIcon.src=ICON_PATH+item.category+'/'+item.id+'.png'; }; Pouch.updateItemRow=function(item){ if(!item._htmlRow){ //create if item row does not exist item._htmlIcon=new Image(); item._htmlIcon.className='item-icon'; item._htmlIcon.loading='lazy'; item._htmlIcon.onerror=function(){ //$(this).off('error'); this.src=ICON_PATH+'unknown.png'; } item._htmlItemId=document.createElement('span'); item._htmlItemId.className='item-name clickable'; item._htmlItemId.id='item-name-'+item.category+'-'+item.index; item._htmlItemId.innerHTML=item.getItemTranslation(); if(item.getItemTranslation()===item.id) item._htmlItemId.style.color='red'; item._htmlItemId.addEventListener('click', function(){ SavegameEditor.editItem(item); }, false); var lastColumn=document.createElement('div'); if(item.category==='weapons' || item.category==='shields' || item.category==='bows') Equipment.buildHtmlElements(item); else if(item.category==='armors') Armor.buildHtmlElements(item); else if(item.category==='food') Item.buildHtmlElements(item); else if(item.category==='horses') Horse.buildHtmlElements(item); else Item.buildHtmlElements(item); $(lastColumn).append(Object.values(item._htmlInputs)); if(item.category==='key' && item.id==='Parasail') $(lastColumn).append(SavegameEditor._htmlSelectParasailPattern); item._htmlRow=document.createElement('div'); item._htmlRow.className='row row-item'; var columnLeft=document.createElement('div'); var columnRight=document.createElement('div'); item._htmlRow.appendChild(columnLeft); item._htmlRow.appendChild(columnRight); columnLeft.appendChild(item._htmlIcon); columnLeft.appendChild(item._htmlItemId); columnRight.appendChild(lastColumn); columnLeft.className='row-item-left'; columnRight.className='row-item-right row-item-right-'+item.category; item._htmlMenuButton=document.createElement('button'); item._htmlMenuButton.appendChild(UI.octicon('kebab_vertical')); item._htmlMenuButton.className='btn-menu-floating'; item._htmlMenuButton.addEventListener('click', function(evt){ evt.stopPropagation(); currentEditingItem=item; var showDivider=false; if(item.category==='weapons'){ $('#dropdown-item-button-pristine').show().prop('disabled', !item.canBeUndecayed()); showDivider=true; }else{ $('#dropdown-item-button-pristine').hide(); } if(item.category==='weapons' || item.category==='bows' || item.category==='shields'){ $('#dropdown-item-button-durability').show().prop('disabled', !item.canBeRestored()); $('#dropdown-item-button-infinite').show().prop('disabled', !item.canBeSetToInfiniteDurability()); showDivider=true; }else{ $('#dropdown-item-button-durability').hide(); $('#dropdown-item-button-infinite').hide(); } if(item.category==='armors' && item.canBeUpgraded()){ $('#dropdown-item-button-upgrade').show(); showDivider=true; }else{ $('#dropdown-item-button-upgrade').hide(); } if(item.category==='weapons' || item.category==='bows' || item.category==='shields' || item.category==='food' || item.category==='horses'){ $('#dropdown-item-button-duplicate').show(); $('#dropdown-item-button-export').show(); $('#dropdown-item-button-import').show(); showDivider=true; }else{ $('#dropdown-item-button-duplicate').hide(); $('#dropdown-item-button-export').hide(); $('#dropdown-item-button-import').hide(); } if(showDivider){ $('#dropdown-item .dropdown-divider').show(); }else{ $('#dropdown-item .dropdown-divider').hide(); } UI.dropdown('item', item._htmlRow); }); item._htmlRow.appendChild(item._htmlMenuButton); item.refreshHtmlInputs(false); Pouch.updateItemIcon(item); }else{ item.refreshHtmlInputs(true); } item._htmlItemId.innerHTML=item.getItemTranslation(); for(var prop in item._htmlInputs){ if(item._htmlInputs[prop].value!=item[prop]) if(item._htmlInputs[prop].percentage) item._htmlInputs[prop].value=item[prop] * 100; else item._htmlInputs[prop].value=item[prop]; } item.lastInputChanged=null; return item._htmlRow; }; Pouch.createItemInput=function(item, propertyName, type, options){ var elementTag=(typeof options.enumValues==='object')? 'select' : 'input'; var className='full-width'; if(type==='Int' || type==='UInt' || type==='Float') className+=' text-right'; var input=document.createElement(elementTag); input.item=item; input.propertyName=propertyName; input.className=className; if(typeof options.label==='string') input.title=options.label; if(elementTag==='select'){ var unknownValue=true; var intValue=typeof item[propertyName]==='string'? hash(item[propertyName]) : item[propertyName]; for(var i=0; i