Files
savegame-editors/nintendogs+cats/nintendogs+cats.js
2025-08-30 17:31:53 +02:00

551 lines
21 KiB
JavaScript

/* eslint-disable max-len */
/*
Nintendogs + Cats for HTML5 Save Editor v?
by Magiczocker 2025
*/
const reg = /\d+/;
const diffs = [ 1056964607, 12582913, 6291456, 4194304 ];
for ( let i = 0; i < 30; i++ ) {
diffs.push( diffs[ diffs.length - 2 ] * 0.5 );
}
let value = 0;
const level_borders = [];
for ( let j = 0; j < 34; j++ ) {
let amount = 1;
if ( j > 3 && j % 2 === 1 ) {
amount = Math.pow( 2, ( j - 1 ) * 0.5 ) - 1;
}
for ( let k = 0; k < amount; k++ ) {
level_borders.push( [ value, value + diffs[ j ] - 1 ] );
value += diffs[ j ];
}
if ( level_borders.length > 99999 ) {
level_borders.length = 100000;
break;
}
}
level_borders[ 99999 ][ 1 ] = 1203982336;
SavegameEditor = {
Name: 'Nintendogs + Cats',
Filename: 'sysdata.dat',
/* Settings */
Settings: {
lang: 'en'
},
/* Constants */
Constants: {
MONEY_OFFSET: 0xA0,
LASTSAVED_OFFSET: 0x10,
GENDERS: [
{ value: 0, name: 'Male' },
{ value: 1, name: 'Female' }
],
STREETPASS_MET_OFFSET: 0x98,
OWNER_POINTS_OFFSET: 0x9C,
PEDOMETER_OFFSET: 0x218,
PET_OFFSET: [
0x026A, // 618
0x1E6A, // 7,786
0x3A6A, // 14,954
0x566A, // 22,122
0x726A, // 29,290
0x8E6A // 36,458
],
PET_NAME_OFFSET: 0x42, // 66
PET_GENDER_OFFSET: 0x56, // 86
PET_POINTS_OFFSET_CAT: 0x5A, // 90
PET_POINTS_OFFSET_DOG: 0x62, // 98
PET_HUNGER_OFFSET: 0x82, // 130
PET_THIRST_OFFSET: 0x86, // 134
PET_COAT_OFFSET: 0x8A, // 138
PET_BREED_OFFSET: 0x32, // 50
PET_BREED_VARIANT_OFFSET: 0x33, // 51 = Variant (e.g. Spaniel = 0:Blentheim, 1:Tricolour, 2:Ruby)
PET_BREED_STYLE_OFFSET: 0x34, // 52 = Hairstyle
PET_BREED_EYE_COLOR_OFFSET: 0x35, // 53 = Eye Color (Cats: 0=gray, 1=yellow, 2=blue; Dogs: 255)
PET_BREED_COLOR_OFFSET: 0x36, // 54 = Fur Color
PET_COMP_CURL_OFFSET3: 0x59, // 89 = Curling Competition
PET_COMP_CURL_OFFSET2: 0x5A, // 90 = Curling Competition
PET_COMP_CURL_OFFSET: 0x5B, // 91 = Curling Competition
PET_COMP_HIGHEST_PLAYED1: 0x5C, // 92 = Highest played difficulty at 'Disc Competition'
PET_COMP_HIGHEST_PLAYED2: 0x5D, // 93 = Highest played difficulty at 'Obedience Competition'
PET_COMP_HIGHEST_PLAYED3: 0x5E, // 94 = Highest played difficulty at 'Lure Competition'
PET_COMP_RANKS: [
{ value: 0, name: 'Nothing' },
{ value: 1, name: 'Junior Cup' },
{ value: 3, name: 'Amateur Cup' },
{ value: 7, name: 'Pro Cup' },
{ value: 15, name: 'Nintendogs Cup' }
],
PET1_COMP_DISC_PLAYED: 0x24E,
PET1_COMP_OBED_PLAYED: 0x24F,
PET1_COMP_LURE_PLAYED: 0x250,
PET2_COMP_DISC_PLAYED: 0x251,
PET2_COMP_OBED_PLAYED: 0x252,
PET2_COMP_LURE_PLAYED: 0x253,
PET3_COMP_DISC_PLAYED: 0x254,
PET3_COMP_OBED_PLAYED: 0x255,
PET3_COMP_LURE_PLAYED: 0x256,
PET4_COMP_DISC_PLAYED: 0x257,
PET4_COMP_OBED_PLAYED: 0x258,
PET4_COMP_LURE_PLAYED: 0x259,
PET5_COMP_DISC_PLAYED: 0x25A,
PET5_COMP_OBED_PLAYED: 0x25B,
PET5_COMP_LURE_PLAYED: 0x25C,
PET6_COMP_DISC_PLAYED: 0x25D,
PET6_COMP_OBED_PLAYED: 0x25E,
PET6_COMP_LURE_PLAYED: 0x25F,
PET_PERSONALITIES_OFFSET_DOG1: 0x1F6,
PET_PERSONALITIES_OFFSET_DOG2: 0x1FA,
PET_PERSONALITIES_OFFSET_CAT1: 0x1EE,
PET_PERSONALITIES_OFFSET_CAT2: 0x1F2,
WALKING_COUNTER_OFFSET: 0x215,
interiors: [
[ '0x208', 'Room_Norse' ],
[ '0x209', 'Room_Japanese' ],
[ '0x20A', 'Room_Asia' ],
[ '0x20B', 'Room_Modern' ],
[ '0x20C', 'Room_Country' ],
[ '0x20D', 'Room_Luxury' ],
[ '0x20E', 'Room_Fairy' ],
[ '0x20F', 'Room_Mario' ],
[ '0x210', 'Room_Future' ]
]
},
_write_money: function () {
tempFile.writeU32(
SavegameEditor.Constants.MONEY_OFFSET,
getValue( 'money' )
);
},
_write_streetpass_met: function () {
tempFile.writeU32(
SavegameEditor.Constants.STREETPASS_MET_OFFSET,
getValue( 'streetpass-met' )
);
},
_write_pedometer: function () {
tempFile.writeU32(
SavegameEditor.Constants.PEDOMETER_OFFSET,
getValue( 'pedometer' )
);
},
_write_walking_counter: function () {
tempFile.writeU8(
SavegameEditor.Constants.WALKING_COUNTER_OFFSET,
getValue( 'walking-counter' )
);
},
_write_supply_amount: function ( e ) {
tempFile.writeU8(
Number( e.target.dataset.offset ),
getValue( e.target.id )
);
},
_write_pet_name: function ( e ) {
const con = SavegameEditor.Constants,
index = Number( ( e.target.id ).match( reg )[ 0 ] ),
offset = con.PET_OFFSET[ index - 1 ] + con.PET_NAME_OFFSET;
tempFile.writeU16String(
offset,
10,
getValue( e.target.id )
);
document.getElementsByClassName( `pet${ index }_name` )[ 0 ].innerText = getValue( e.target.id );
},
_write_u_number: function ( e, n, o, g ) {
const index = Number( ( e.target.id ).match( reg )[ 0 ] );
let pet_offset = SavegameEditor.Constants.PET_OFFSET[ index - 1 ];
if ( g ) {
pet_offset = 0;
}
const offset = pet_offset + SavegameEditor.Constants[ o ];
tempFile[ `writeU${ n }` ](
offset,
Number( getValue( e.target.id ) )
);
},
_write_pet_value: function ( e ) {
SavegameEditor._write_u_number( e, Number( e.target.parentElement.dataset.size ), e.target.parentElement.dataset.var, e.target.parentElement.dataset.global );
},
_getPetData( petOffset, val, size ) {
return tempFile[ `readU${ size || 8 }` ]( SavegameEditor.Constants.PET_OFFSET[ petOffset ] + SavegameEditor.Constants[ val ] );
},
_mark_as_changed( e ) {
e.target.dataset.data_changed = true;
},
/* check if savegame is valid */
checkValidSavegame: function () {
return ( tempFile.fileSize === 60936 );
},
updateInterior: function () {
tempFile.writeU8(
0x207,
getValue( 'interiors' )
);
},
setPos: function ( node, pos ) {
const size = 64, // Sprite height
scale = 0.5, // height scaled down to 32px
tiles = 18,
left = pos % tiles * size * scale,
top = Math.floor( pos / tiles ) * size * scale;
node.style.backgroundPosition = `-${ left }px -${ top }px`;
},
appendItems: function () {
const itemTypes = [
[ 'fooddrink', 99 ],
[ 'toys', 99 ],
[ 'accessories', 99 ],
[ 'furnitures', 99 ],
[ 'leashes', 99 ],
[ 'bowlsdrink', 1 ],
[ 'bowlsfood', 1 ]
];
SavegameEditor.Constants.items.forEach( ( item, index ) => {
const type = itemTypes[ item[ 0 ] ],
rowname = type[ 0 ],
min = [ 'bowlsfood', 'bowlsdrink' ].includes( rowname ) ? 1 : 0,
row = get( `row-${ rowname }` ),
itemIcon = document.createElement( 'span' ),
itemCol = col( 3, itemIcon ),
itemName = itemCol.appendChild( document.createElement( 'span' ) ),
itemInput = inputNumber( `supplies_${ index }`, index === 0 ? min : 0, type[ 1 ], tempFile.readU8( Number( item[ 2 ] ) ) );
itemIcon.className = 'item-icon';
itemName.className = 'item-name';
itemName.dataset.translate = item[ 1 ];
SavegameEditor.setPos( itemIcon, index );
row.append( itemCol );
row.append(
col( 1, itemInput )
);
itemInput.dataset.offset = item[ 2 ];
itemInput.addEventListener( 'change', SavegameEditor._write_supply_amount );
} );
itemTypes.forEach( ( type ) => {
const rowname = type[ 0 ],
row = get( `row-${ rowname }` ),
lastRow = row.childElementCount % 6;
if ( lastRow !== 0 ) {
row.append( col( ( 6 - lastRow ) * 2, span( '' ) ) );
}
} );
},
appendInteriors: function () {
const options = [],
row = get( 'row-interiors' );
SavegameEditor.Constants.interiors.forEach( ( interior, index ) => {
const input = inputNumber( `interiors_${ index }`, 0, interior[ 1 ], tempFile.readU8( Number( interior[ 0 ] ) ) );
const textEle = span( '' );
textEle.dataset.translate = interior[ 1 ];
row.append(
col( 3, textEle ),
col( 1, input )
);
input.dataset.offset = interior[ 0 ];
input.addEventListener( 'change', SavegameEditor._write_supply_amount );
options.push( interior[ 1 ] );
} );
const opt = select( 'interiors', options, SavegameEditor.updateInterior );
row.prepend( col( 4, opt ) );
row.prepend( col( 8, span( 'Active interior' ) ) );
for ( let i = 0; i < opt.length; i++ ) {
if ( opt[ i ].nodeName === 'OPTION' ) {
opt[ i ].dataset.translate = opt[ i ].textContent;
}
}
},
/* settings */
loadSettings: function () {
if ( typeof localStorage === 'object' && localStorage.getItem( 'nintendogs-cats-settings' ) ) {
const loadedSettings = JSON.parse( localStorage.getItem( 'nintendogs-cats-settings' ) );
if ( typeof loadedSettings.lang === 'string' ) {
this.Settings.lang = loadedSettings.lang.toLowerCase().trim();
}
}
},
saveSettings: function () {
if ( typeof localStorage === 'object' ) {
localStorage.setItem( 'nintendogs-cats-settings', JSON.stringify( this.Settings ) );
}
},
preload: function () {
setNumericRange( 'money', 0, 9999999 );
setNumericRange( 'streetpass-met', 0, 9999999 );
setNumericRange( 'pedometer', 0, 9999999 );
setNumericRange( 'walking-counter', 0, 255 );
setNumericRange( 'owner-points', 0, 99999 );
const level_ele_ = get( 'number-owner-points' );
level_ele_.addEventListener( 'change', SavegameEditor._mark_as_changed );
const btn_last_saved = document.getElementById( 'update-lastsaved' );
btn_last_saved.addEventListener( 'click', () => {
tempFile.writeU32(
SavegameEditor.Constants.LASTSAVED_OFFSET,
Math.floor( Date.now() * 0.001 )
);
const a = new Date( Number( tempFile.readU32( SavegameEditor.Constants.LASTSAVED_OFFSET ) ) * 1000 );
a.setHours( a.getHours() - a.getTimezoneOffset() / 60 );
setValue( 'lastsaved', a.toLocaleString( 'en-GB', {
day: 'numeric',
month: 'short',
year: 'numeric',
hour: '2-digit',
minute: '2-digit',
second: '2-digit'
} ) );
}, false );
get( 'number-money' ).addEventListener( 'change', SavegameEditor._write_money );
get( 'number-streetpass-met' ).addEventListener( 'change', SavegameEditor._write_streetpass_met );
get( 'number-pedometer' ).addEventListener( 'change', SavegameEditor._write_pedometer );
get( 'number-walking-counter' ).addEventListener( 'change', SavegameEditor._write_walking_counter );
SavegameEditor.appendItems();
SavegameEditor.appendInteriors();
Locale.set( SavegameEditor.Settings.lang );
},
unload: function () {
document.getElementById( 'container-startup' ).style.removeProperty( 'display' );
},
/* load function */
load: function () {
document.getElementById( 'container-startup' ).style.display = 'none';
tempFile.fileName = 'sysdata.dat';
tempFile.littleEndian = true;
setValue( 'money', tempFile.readU32( SavegameEditor.Constants.MONEY_OFFSET ) );
setValue( 'streetpass-met', tempFile.readU32( SavegameEditor.Constants.STREETPASS_MET_OFFSET ) );
setValue( 'pedometer', tempFile.readU32( SavegameEditor.Constants.PEDOMETER_OFFSET ) );
setValue( 'walking-counter', tempFile.readU8( SavegameEditor.Constants.WALKING_COUNTER_OFFSET ) );
const owner_points = tempFile.readU32( SavegameEditor.Constants.OWNER_POINTS_OFFSET );
for ( let k = 0; k < level_borders.length; k++ ) {
if ( owner_points >= level_borders[ k ][ 0 ] && owner_points <= level_borders[ k ][ 1 ] ) {
setValue( 'owner-points', k );
break;
}
}
// Update supply-values
const supply_values = document.querySelectorAll( '[id^=number-supplies_]' );
supply_values.forEach( ( t ) => {
t.value = tempFile.readU8( Number( t.dataset.offset ) );
} );
// Update interior-values
SavegameEditor.Constants.interiors.forEach( ( interior, index ) => {
const input = get( `number-interiors_${ index }` );
input.value = tempFile.readU8( Number( input.dataset.offset ) );
} );
const a = new Date( Number( tempFile.readU32( SavegameEditor.Constants.LASTSAVED_OFFSET ) ) * 1000 );
setValue( 'lastsaved', a.toLocaleString( 'en-GB', {
day: 'numeric',
month: 'short',
year: 'numeric',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
timezone: 'Europe/London'
} ) );
const template = document.getElementById( 'template-row-pet' );
const pet_tabs = document.getElementById( 'pet_tabs' );
pet_tabs.innerText = '';
const pet_tabs_content_seperator = document.createElement( 'div' );
pet_tabs.appendChild( pet_tabs_content_seperator );
let first_pet = true;
for ( let i = 1; i < 7; i++ ) {
const pet_present = tempFile.readU8( SavegameEditor.Constants.PET_OFFSET[ i - 1 ] ) > 0;
if ( !pet_present ) {
continue;
}
const pet_tab_input = document.createElement( 'input' );
pet_tab_input.name = 'pet_tabgroup';
pet_tab_input.type = 'radio';
pet_tab_input.id = `pet_tab${ i }`;
pet_tab_input.className = 'pet_tab';
if ( first_pet ) {
pet_tab_input.checked = true;
first_pet = false;
}
pet_tabs.insertBefore( pet_tab_input, pet_tabs_content_seperator );
const pet_tab_label = document.createElement( 'label' );
pet_tab_label.className = 'pet_label';
pet_tab_label.setAttribute( 'for', `pet_tab${ i }` );
pet_tabs.insertBefore( pet_tab_label, pet_tabs_content_seperator );
const templateClone = template.content.cloneNode( true );
templateClone.querySelector( '.row' ).id = `row-pet${ i }`;
for ( const ele of templateClone.querySelectorAll( '.update-name' ) ) {
if ( ( ele.id || '' ).includes( 'petX' ) ) {
ele.id = ele.id.replace( /petX/g, `pet${ i }` );
}
if ( ele.getAttribute( 'for' ) ) {
ele.setAttribute( 'for', ele.getAttribute( 'for' ).replace( /petX/g, `pet${ i }` ) );
}
if ( ( ele.dataset && ele.dataset.var || '' ).includes( 'PETX' ) ) {
ele.dataset.var = ele.dataset.var.replace( /PETX/g, `PET${ i }` );
}
}
const breed = SavegameEditor._getPetData( i - 1, 'PET_BREED_OFFSET' );
let isDog = true;
if ( breed > 28 && breed < 32 ) {
isDog = false;
}
pet_tabs.appendChild( templateClone );
const dialogClassName = 'page-' +
breed +
'-' +
SavegameEditor._getPetData( i - 1, 'PET_BREED_VARIANT_OFFSET' );
const dialogEle = document.getElementsByClassName(
dialogClassName
)[ 0 ];
if ( !isDog ) {
document.getElementById( 'eyecolor' ).querySelector( '[data-offset="' + SavegameEditor._getPetData( i - 1, 'PET_BREED_EYE_COLOR_OFFSET' ) + '"]' ).checked = true;
}
window._sidebar_event( {
target: dialogEle
} );
let breedImg = document.createElement( 'img' );
const breedImgTmp = document
.getElementById( 'menu-content' )
.getElementsByClassName( dialogClassName )[ 0 ]
.querySelector( 'div[data-color="' + SavegameEditor._getPetData( i - 1, 'PET_BREED_COLOR_OFFSET' ) + '"][data-style="' + SavegameEditor._getPetData( i - 1, 'PET_BREED_STYLE_OFFSET' ) + '"]'
);
if ( breedImgTmp ) {
breedImg = breedImgTmp.cloneNode();
breedImg.id = `petimage${ i }`;
}
get( `container-pet${ i }-breed` ).appendChild( breedImg );
const breedImg2 = breedImg.cloneNode();
breedImg2.id = '';
pet_tab_label.appendChild( breedImg2 );
const dialogbtn = document.createElement( 'button' );
dialogbtn.dataset.pet = i - 1;
// eslint-disable-next-line no-loop-func
dialogbtn.onclick = function ( e ) {
e.preventDefault();
get( 'menu' ).dataset.pet = e.target.dataset.pet;
get( 'menu' ).showModal();
const breed_ = SavegameEditor._getPetData( e.target.dataset.pet, 'PET_BREED_OFFSET' );
const dialogClassName_ = 'page-' +
breed_ +
'-' +
SavegameEditor._getPetData( e.target.dataset.pet, 'PET_BREED_VARIANT_OFFSET' );
const dialogEle_ = document.getElementsByClassName(
dialogClassName_
)[ 0 ];
if ( breed_ > 28 && breed_ < 32 ) {
document.getElementById( 'eyecolor' ).querySelector( '[data-offset="' + SavegameEditor._getPetData( e.target.dataset.pet, 'PET_BREED_EYE_COLOR_OFFSET' ) + '"]' ).checked = true;
}
window._sidebar_event( {
target: dialogEle_
} );
};
dialogbtn.innerText = 'Change';
get( `container-pet${ i }-breed` ).appendChild( dialogbtn );
get( `container-pet${ i }-gender` ).appendChild( select( `pet${ i }-gender`, SavegameEditor.Constants.GENDERS, SavegameEditor._write_pet_value ) );
setValue( `pet${ i }-name`, tempFile.readU16String( SavegameEditor.Constants.PET_OFFSET[ i - 1 ] + SavegameEditor.Constants.PET_NAME_OFFSET, 10 ) );
const pet_tab_label_name = document.createElement( 'span' );
pet_tab_label_name.innerText = getValue( `pet${ i }-name` );
pet_tab_label_name.className = `pet${ i }_name`;
pet_tab_label.appendChild( pet_tab_label_name );
setValue( `pet${ i }-gender`, SavegameEditor._getPetData( i - 1, 'PET_GENDER_OFFSET' ) );
get( `input-pet${ i }-name` ).addEventListener( 'change', SavegameEditor._write_pet_name );
setNumericRange( `pet${ i }-disc-played`, 0, 2 );
setValue( `pet${ i }-disc-played`, tempFile.readU8( SavegameEditor.Constants[ `PET${ i }_COMP_DISC_PLAYED` ] ) );
get( `number-pet${ i }-disc-played` ).addEventListener( 'change', SavegameEditor._write_pet_value );
setNumericRange( `pet${ i }-lure-played`, 0, 2 );
setValue( `pet${ i }-lure-played`, tempFile.readU8( SavegameEditor.Constants[ `PET${ i }_COMP_LURE_PLAYED` ] ) );
get( `number-pet${ i }-lure-played` ).addEventListener( 'change', SavegameEditor._write_pet_value );
setNumericRange( `pet${ i }-obed-played`, 0, 2 );
setValue( `pet${ i }-obed-played`, tempFile.readU8( SavegameEditor.Constants[ `PET${ i }_COMP_OBED_PLAYED` ] ) );
get( `number-pet${ i }-obed-played` ).addEventListener( 'change', SavegameEditor._write_pet_value );
if ( isDog ) {
get( `container-pet${ i }-disc` ).appendChild( select( `pet${ i }-disc`, SavegameEditor.Constants.PET_COMP_RANKS, SavegameEditor._write_pet_value ) );
setValue( `pet${ i }-disc`, SavegameEditor._getPetData( i - 1, 'PET_COMP_HIGHEST_PLAYED1' ) );
get( `container-pet${ i }-lure` ).appendChild( select( `pet${ i }-lure`, SavegameEditor.Constants.PET_COMP_RANKS, SavegameEditor._write_pet_value ) );
setValue( `pet${ i }-lure`, SavegameEditor._getPetData( i - 1, 'PET_COMP_HIGHEST_PLAYED3' ) );
get( `container-pet${ i }-obedience` ).appendChild( select( `pet${ i }-obedience`, SavegameEditor.Constants.PET_COMP_RANKS, SavegameEditor._write_pet_value ) );
setValue( `pet${ i }-obedience`, SavegameEditor._getPetData( i - 1, 'PET_COMP_HIGHEST_PLAYED2' ) );
} else {
get( `pet${ i }_comp_outer` ).style.display = 'none';
}
const personality = SavegameEditor.Constants.personalities[ SavegameEditor._getPetData( i - 1, 'PET_PERSONALITIES_OFFSET_' + ( isDog ? 'DOG' : 'CAT' ) + '1', 8 ) ][ SavegameEditor._getPetData( i - 1, 'PET_PERSONALITIES_OFFSET_' + ( isDog ? 'DOG' : 'CAT' ) + '2', 8 ) ];
setValue( `pet${ i }-personality`, personality[ Number( SavegameEditor._getPetData( i - 1, 'PET_GENDER_OFFSET' ) ) ] );
// Experimental
setNumericRange( `pet${ i }-hunger`, 0, 17529 );
setNumericRange( `pet${ i }-thirst`, 0, 17529 );
setNumericRange( `pet${ i }-coat`, 0, 17529 );
setValue( `pet${ i }-hunger`, SavegameEditor._getPetData( i - 1, 'PET_HUNGER_OFFSET', 16 ) );
setValue( `pet${ i }-thirst`, SavegameEditor._getPetData( i - 1, 'PET_THIRST_OFFSET', 16 ) );
setValue( `pet${ i }-coat`, SavegameEditor._getPetData( i - 1, 'PET_COAT_OFFSET', 16 ) );
get( `number-pet${ i }-hunger` ).addEventListener( 'change', SavegameEditor._write_pet_value );
get( `number-pet${ i }-thirst` ).addEventListener( 'change', SavegameEditor._write_pet_value );
get( `number-pet${ i }-coat` ).addEventListener( 'change', SavegameEditor._write_pet_value );
setNumericRange( `pet${ i }-level`, 0, 99999 );
const points = SavegameEditor._getPetData( i - 1, ( isDog ? 'PET_POINTS_OFFSET_DOG' : 'PET_POINTS_OFFSET_CAT' ), 32 );
for ( let j = 0; j < level_borders.length; j++ ) {
if ( points >= level_borders[ j ][ 0 ] && points <= level_borders[ j ][ 1 ] ) {
setValue( `pet${ i }-level`, j );
break;
}
}
const level_ele = get( `number-pet${ i }-level` );
level_ele.dataset.is_dog = isDog;
level_ele.addEventListener( 'change', SavegameEditor._mark_as_changed );
}
pet_tabs.removeChild( pet_tabs_content_seperator );
},
/* save function */
save: function () {
tempFile.writeU8( 0x13D, 0 );
const changed_levels = document.querySelectorAll( '[data-data_changed]' );
for ( let i = 0; i < changed_levels.length; i++ ) {
const value_old = changed_levels[ i ].value;
setNumericRange( changed_levels[ i ].id.slice( 7 ) );
changed_levels[ i ].value = level_borders[ changed_levels[ i ].value ][ 0 ];
if ( changed_levels[ i ].id === 'number-owner-points' ) {
tempFile.writeU32(
SavegameEditor.Constants.OWNER_POINTS_OFFSET,
getValue( 'owner-points' )
);
} else {
SavegameEditor._write_u_number(
{ target: { id: changed_levels[ i ].id } },
32,
changed_levels[ i ].dataset.is_dog ? 'PET_POINTS_OFFSET_DOG' : 'PET_POINTS_OFFSET_CAT'
);
}
changed_levels[ i ].value = value_old;
delete changed_levels[ i ].dataset.data_changed;
setNumericRange( changed_levels[ i ].id.slice( 0, 99999 ) );
}
}
};
window.addEventListener( 'DOMContentLoaded', () => {
SavegameEditor.loadSettings();
document.getElementById( 'select-language' ).value = SavegameEditor.Settings.lang;
document.getElementById( 'select-language' ).addEventListener( 'change', ( e ) => {
SavegameEditor.Settings.lang = e.target.value;
Locale.set( e.target.value );
SavegameEditor.saveSettings();
} );
} );