From 0ea37a7239abe1d1a0f9481caae91e1f89b260d4 Mon Sep 17 00:00:00 2001 From: jgl <jgl6@protonmail.com> Date: Mon, 6 Nov 2023 09:14:52 +0100 Subject: [PATCH] Restore custom animal functionality --- js/003-data/gameVariableData.js | 3 +- src/facilities/farmyard/animals/Animal.js | 22 ++++- src/facilities/farmyard/animals/animals.js | 94 ++++++++++++++++------ 3 files changed, 94 insertions(+), 25 deletions(-) diff --git a/js/003-data/gameVariableData.js b/js/003-data/gameVariableData.js index fdbcf4cf2bb..ded5a1b0ef6 100644 --- a/js/003-data/gameVariableData.js +++ b/js/003-data/gameVariableData.js @@ -755,6 +755,7 @@ App.Data.resetOnNGPlus = { /** @type {string[]} */ feline: [], }, + customAnimals: [], farmyardName: "the Farmyard", HGSuite: 0, @@ -1300,7 +1301,7 @@ App.Data.resetOnNGPlus = { raGrowthExpr: 0, sexOverhaul: 0, interactions: 0, - clitoralPenetration : 0, + clitoralPenetration: 0, raSortOutput: 0, favSeparateReport: 0, }, diff --git a/src/facilities/farmyard/animals/Animal.js b/src/facilities/farmyard/animals/Animal.js index 7f30b113735..ebcc0b9ec8d 100644 --- a/src/facilities/farmyard/animals/Animal.js +++ b/src/facilities/farmyard/animals/Animal.js @@ -30,6 +30,11 @@ App.Entity.Animal = class Animal { return V.active[this.type] === this.name; } + /** @returns {boolean} */ + get isCustom() { + return V.customAnimals.find(animal => animal.name === this.name); + } + /** @returns {string} */ get ballType() { return this.species; @@ -48,6 +53,8 @@ App.Entity.Animal = class Animal { /** @returns {this} */ sell() { + V.animals[this.type] = V.animals[this.type].filter(animal => animal !== this.name); + if (this.isActive) { V.active[this.type] = V.animals[this.type].random() || null; } @@ -56,11 +63,24 @@ App.Entity.Animal = class Animal { V.pit.animal = null; } */ - V.animals[this.type] = V.animals[this.type].filter(animal => animal !== this.name); return this; } + /** @returns {boolean} Removal succeeded */ + remove() { + if (!this.isCustom) { + throw Error('Unable to remove default animal.'); + } + const index = V.customAnimals.findIndex(animal => animal.name === this.name); + if (~index) { + V.customAnimals.splice(index, 1); + App.Data.animals.delete(this); + return true; + } + return false; + } + /** @param {string} name */ setName(name) { this.name = name; diff --git a/src/facilities/farmyard/animals/animals.js b/src/facilities/farmyard/animals/animals.js index 9ffffda389e..b78710845a1 100644 --- a/src/facilities/farmyard/animals/animals.js +++ b/src/facilities/farmyard/animals/animals.js @@ -12,7 +12,7 @@ App.Facilities.Farmyard.animals = function() { App.UI.DOM.appendNewElement("div", frag, domestic(), ['margin-bottom']); App.UI.DOM.appendNewElement("div", frag, exotic(), ['margin-bottom']); - // frag.append(addAnimal()); // FIXME: causes save corruption. + frag.append(addAnimal()); V.nextButton = "Back"; V.nextLink = "Farmyard"; @@ -279,32 +279,34 @@ App.Facilities.Farmyard.animals = function() { * @param {function():void} param.setActiveHandler * @param {function():void} param.purchaseHandler * @param {function():void} param.sellHandler + * @param {function():void} param.removeCustomHandler * @returns {string|HTMLElement} */ - function animalLink({animal, active, type, price, setActiveHandler, purchaseHandler, sellHandler}) { - if (animal.purchased || V.animals[animal.type].some(a => a === animal.name)) { - const div = document.createElement("div"); - - const options = []; + function animalLink({ + animal, active, type, price, setActiveHandler, purchaseHandler, sellHandler, removeCustomHandler + }) { + const div = document.createElement("div"); + const options = []; - if (V.active[active] && V.active[active] === animal.name) { - options.push( - App.UI.DOM.disabledLink(`Set as active ${type}`, ['Already set as active']), - App.UI.DOM.link(`Sell`, sellHandler) - ); + if (animal.purchased || V.animals[animal.type].some(a => a === animal.name)) { + if (V.active[active] && animal.isActive) { + options.push(App.UI.DOM.disabledLink(`Set as active ${type}`, ['Already set as active'])); } else { - options.push( - App.UI.DOM.link(`Set as active ${type}`, setActiveHandler), - App.UI.DOM.link(`Sell`, sellHandler) - ); + options.push(App.UI.DOM.link(`Set as active ${type}`, setActiveHandler)); } + options.push(App.UI.DOM.link(`Sell`, sellHandler)); + } else { + div.append(makePurchase(`Purchase ${animal.articleAn} ${animal.name}`, price, "farmyard", {notes: [`will incur upkeep costs`], handler: purchaseHandler})); + } - div.append(App.UI.DOM.generateLinksStrip(options)); + if (animal.isCustom) { + options.push(App.UI.DOM.link(`Remove custom ${type}`, removeCustomHandler)); + } - return div; - } else { - return makePurchase(`Purchase ${animal.articleAn} ${animal.name}`, price, "farmyard", {notes: [`will incur upkeep costs`], handler: purchaseHandler}); + if (options.length) { + div.append(App.UI.DOM.generateLinksStrip(options)); } + return div; } /** @@ -336,11 +338,10 @@ App.Facilities.Farmyard.animals = function() { price: price, setActiveHandler() { animal.setActive(); - App.UI.DOM.replace(div, animalList(type, rarity, price, active)); + App.UI.DOM.replace(div, animalList(type, rarity, price, active, species, exclude)); App.UI.DOM.replace(activeDiv, activeAnimals()); }, purchaseHandler() { - cashX(forceNeg(price), "farmyard"); animal.purchase(); if (!V.active[animal.type]) { animal.setActive(); @@ -354,6 +355,15 @@ App.Facilities.Farmyard.animals = function() { App.UI.DOM.replace(activeDiv, activeAnimals()); App.UI.DOM.replace(div, animalList(type, rarity, price, active, species, exclude)); }, + removeCustomHandler() { + if (animal.purchased || V.animals[animal.type].some(a => a === animal.name)) { + cashX(price * 0.75, "farmyard"); + animal.sell(); + } + animal.remove(); + App.UI.DOM.replace(activeDiv, activeAnimals()); + App.UI.DOM.replace(div, animalList(type, rarity, price, active, species, exclude)); + } }; optionDiv.append(animalLink(args)); @@ -365,7 +375,6 @@ App.Facilities.Farmyard.animals = function() { return div; } - // FIXME: added animals are just blindly shoved into session data and make the game will crash when a save is loaded in a different session function addAnimal() { const frag = new DocumentFragment(); @@ -531,11 +540,16 @@ App.Facilities.Farmyard.animals = function() { disabledReasons.push(`Animal must have a species.`); } + if (getAnimal(animal.name)) { + disabledReasons.push(`Animal with the same name already exists.`); + } + if (disabledReasons.length > 0) { App.UI.DOM.appendNewElement("div", addDiv, App.UI.DOM.disabledLink(`Add`, disabledReasons), ['margin-top']); } else { App.UI.DOM.appendNewElement("div", addDiv, App.UI.DOM.link(`Add`, () => { App.Data.animals.add(animal); + V.customAnimals.push(animal); App.UI.reload(); }), ['margin-top']); @@ -572,7 +586,7 @@ globalThis.getAnimal = function(name) { App.Facilities.Farmyard.animals.init = function() { if (!App.Data.animals || App.Data.animals.size === 0) { - class Animal extends App.Entity.Animal {} + class Animal extends App.Entity.Animal { } const dog = 'dog'; const cat = 'cat'; @@ -639,6 +653,40 @@ App.Facilities.Farmyard.animals.init = function() { new Animal("puma", "puma", feline, exotic), new Animal("tiger", "tiger", feline, exotic), ].forEach(animal => App.Data.animals.add(animal)); + + /** @param {Animal} data */ + const restoreAnimal = function(data) { + const {name, species, type, rarity, dick, deadliness, articleAn} = data; + if (!name || !species || !type || !rarity) { + return; + } + + const animal = new Animal(name, species, type, rarity); + + if (dick && dick.size) { + animal.setDick(dick.size, dick.desc); + } + if (deadliness) { + animal.setDeadliness(deadliness); + } + if (articleAn && (articleAn === 'a' || articleAn === 'an')) { + animal.setArticle(articleAn); + } + return animal; + }; + + for (const animalData of V.customAnimals) { + const animal = restoreAnimal(animalData); + if (animal) { + App.Data.animals.add(animal); + } else { + const index = V.customAnimals.indexOf(animalData); + if (~index) { + V.customAnimals.splice(index, 1); + console.error('Invalid custom animal removed: ', animalData); + } + } + } } }; -- GitLab