From 28807ae0ebfab51e435fbe98d516018244f2c528 Mon Sep 17 00:00:00 2001 From: SilenceFactor <149717374+SilenceFactor@users.noreply.github.com> Date: Tue, 16 Apr 2024 21:26:33 +0200 Subject: [PATCH] Sorting and favorite system - Kittens can be sorted - There are pages in the census - Kittens can be favorited, and favorite kittens are prioritized when you reset with cryochambers - If a kitten is an engineer census now also lists what they are crafting. --- game.js | 2 + js/village.js | 237 +++++++++++++++++++++++++++++++++++++++++++++-- res/i18n/en.json | 10 +- 3 files changed, 239 insertions(+), 10 deletions(-) diff --git a/game.js b/game.js index 49fd6bfb92..570b5945d4 100644 --- a/game.js +++ b/game.js @@ -4854,10 +4854,12 @@ dojo.declare("com.nuclearunicorn.game.ui.GamePage", null, { if (cryochambers > 0) { this.village.sim.sortKittensByExp(); + this.village.sim.sortKittensByFavorite(); newKittens = this.village.sim.kittens.slice(-cryochambers); for (var i in newKittens) { delete newKittens[i].job; delete newKittens[i].engineerSpeciality; + newKittens[i].favorite = true; } var usedCryochambers_reset = this.time.filterMetadata([this.time.getVSU("usedCryochambers")], ["name", "val", "on"]); usedCryochambers_reset[0]["val"] = cryochambers; diff --git a/js/village.js b/js/village.js index 2ead1392be..05bb5dfee0 100644 --- a/js/village.js +++ b/js/village.js @@ -1083,6 +1083,7 @@ dojo.declare("com.nuclearunicorn.game.village.Kitten", null, { //obsolete isSenator: false, + favorite: false, constructor: function(){ this.name = this.names[this.rand(this.names.length)]; @@ -1145,6 +1146,7 @@ dojo.declare("com.nuclearunicorn.game.village.Kitten", null, { this.color = data.color || 0; this.variety = data.variety || 0; this.rarity = data.rarity || 0; + this.favorite = data.favorite || false; for (var job in this.skills) { if (this.skills[job] > 20001) { @@ -1181,6 +1183,7 @@ dojo.declare("com.nuclearunicorn.game.village.Kitten", null, { this.isLeader = data.isLeader || false; this.isSenator = false; this.isAdopted = data.isAdopted || false; + this.favorite = data.favorite || false; }, /** @@ -1224,7 +1227,8 @@ dojo.declare("com.nuclearunicorn.game.village.Kitten", null, { engineerSpeciality: this.engineerSpeciality || undefined, rank: this.rank || undefined, isLeader: this.isLeader || undefined, - isAdopted: this.isAdopted || undefined + isAdopted: this.isAdopted || undefined, + favorite: this.favorite || undefined }; }, @@ -1260,7 +1264,8 @@ dojo.declare("com.nuclearunicorn.game.village.Kitten", null, { engineerSpeciality: this.engineerSpeciality || undefined, rank: this.rank || undefined, isLeader: this.isLeader || undefined, - isAdopted: this.isAdopted || undefined + isAdopted: this.isAdopted || undefined, + favorite: this.favorite || undefined }; // Custom sur/names if (nameIndex <= 0 || surnameIndex <= 0) { @@ -2257,6 +2262,41 @@ dojo.declare("classes.village.KittenSim", null, { }); }, + sortKittensByFavorite: function(){ + this.sortKittensByExp(); + this.kittens.sort(function(a,b) { + if(a.favorite == b.favorite){ + return 0; + } else { + return a.favorite? 1 : -1; + } + }); + }, + + sortKittensByColor: function(){ + this.sortKittensByExp(); + this.kittens.sort(function(a,b) { + if(a.color || b.color){ + if(a.color && b.color){ + return 0; + } + return a.color? 1 : -1; + } + }); + }, + + sortKittensByVariety: function(){ + this.sortKittensByExp(); + this.kittens.sort(function(a,b) { + if(a.variety || b.variety) { + if(a.variety && b.variety){ + return 0; + } + return a.variety? 1 : -1; + } + }); + }, + getKittens: function(){ return this.kittens.length; }, @@ -3436,6 +3476,21 @@ dojo.declare("classes.ui.village.Census", null, { filterJob: null, filterTrait: null, + startKitten: 0, + sortKittens: null, + sortOptions: [{ + name: "exp", + title: $I("village.census.sort.exp") + },{ + name: "favorite", + title: $I("village.census.sort.favorite") + },{ + name: "color", + title: $I("village.census.sort.color") + },{ + name: "variety", + title: $I("village.census.sort.variety") + }], constructor: function(game){ this.game = game; @@ -3474,6 +3529,7 @@ dojo.declare("classes.ui.village.Census", null, { dojo.connect(traitSelect, "onchange", this, function (event) { this.filterTrait = event.target.value; + this.startKitten = 0; this.render(this.container); }); @@ -3495,22 +3551,80 @@ dojo.declare("classes.ui.village.Census", null, { dojo.connect(jobSelect, "onchange", this, function(event){ var job = event.target.value; + this.startKitten = 0; this.filterJob = job; this.render(this.container); }); - var kittensLimit = 0; + //--------------- sorting ----------------- + + var selectSorting = dojo.create("select", { style: {float: "right" }}, navbar); + + for (var i = 0; i < this.sortOptions.length; i++){ + var option = this.sortOptions[i]; + dojo.create("option", { value: option.name, innerHTML: option.title, selected: (option.name == this.sortKittens)}, selectSorting); + } + + dojo.connect(selectSorting, "onchange", this, function(event){ + var sorting = event.target.value; + this.sortKittens = sorting; + this.startKitten = 0; + this.render(this.container); + }); var sim = this.game.village.sim; - sim.sortKittensByExp(); + if(!this.sortKittens){ + sim.sortKittensByExp(); //When switching to this tab, the default sorting is used. + } + + switch (this.sortKittens) { + case "exp": + sim.sortKittensByExp(); + break; + case "favorite": + sim.sortKittensByFavorite(); + break; + case "color": + sim.sortKittensByColor(); + break; + case "variety": + sim.sortKittensByVariety(); + } + + var filterKittens = 0; + var start = this.startKitten; + // Filters work differently from sorting as they skip kittens, because of this a workaround is used + if(this.filterJob || this.filterTrait){ + filterKittens = sim.kittens.length; + for(var i in sim.kittens){ + var kitten = sim.kittens[i]; + if ((this.filterJob && kitten.job !== this.filterJob) || (this.filterTrait && kitten.trait.name !== this.filterTrait)) { + filterKittens--; + } + } + + var maxStart = Math.floor(filterKittens / 10) * 10; + filterKittens = Math.floor(Math.min(this.startKitten, filterKittens) / 10) * 10; + if (filterKittens == maxStart && filterKittens > 0){ //Used to prevent empty pages + filterKittens -= 10; + } + this.startKitten = filterKittens; + start = 0; + } - for (var i = sim.kittens.length - 1; i >= 0 && kittensLimit < 10; i--) { + var kittensLimit = 0; + + for (var i = sim.kittens.length - (1 + start); i >= 0 && kittensLimit < 10; i--) { var kitten = sim.kittens[i]; if ((this.filterJob && kitten.job !== this.filterJob) || (this.filterTrait && kitten.trait.name !== this.filterTrait)) { continue; } + if(filterKittens > 0){ + filterKittens--; + continue; + } kittensLimit++; @@ -3548,6 +3662,15 @@ dojo.declare("classes.ui.village.Census", null, { }, linksDiv); } + var favoriteHref = dojo.create("a", { + href: "#", innerHTML: "", + className: "favoriteHref", + style: { + float: "right" + }, + title: "Favorite kitten" + }, linksDiv); + var unassignHref = dojo.create("a", { href: "#", innerHTML: $I("village.btn.unassign.job"), className: "unassignHref", @@ -3565,6 +3688,12 @@ dojo.declare("classes.ui.village.Census", null, { }, this.game, i)); + dojo.connect(favoriteHref, "onclick", this, dojo.partial(function(game, i){ + var kitten = game.village.sim.kittens[i]; + kitten.favorite = !kitten.favorite; + this.render(this.container); + }, this.game, i)); + if (!this.game.challenges.isActive("anarchy")) { dojo.connect(leaderHref, "onclick", this, dojo.partial(function(census, i, event){ event.preventDefault(); @@ -3589,9 +3718,86 @@ dojo.declare("classes.ui.village.Census", null, { kitten: kitten, unassignHref: unassignHref, /*senatorHref: senatorHref,*/ - leaderHref: leaderHref + leaderHref: leaderHref, + favoriteHref: favoriteHref }); } + + //--------------- Page Switching ----------------- + + var pageNumber = Math.floor(this.startKitten / 10) + 1; + + var pageSwitchDiv = dojo.create("div", { + innerHTML: pageNumber, + style: { + display: "inline-block", + width: "100%", + textAlign: "center", + margin: "0 auto" + } + }, container); + //--------------- Last page ----------------- + var lastHref = dojo.create("a", { + href: "#", innerHTML: ">>", + className: "lastHref", + style: { + float: "right" + } + }, pageSwitchDiv); + + dojo.connect(lastHref, "onclick", this, dojo.partial(function(){ + this.startKitten = sim.kittens.length / 10; + if (Math.floor(this.startKitten) == this.startKitten){ + this.startKitten -= 1; + } + this.startKitten = Math.floor(this.startKitten) * 10; + this.render(this.container); + })); + //--------------- Next page ----------------- + var nextHref = dojo.create("a", { + href: "#", innerHTML: $I("village.btn.next"), + className: "nextHref", + style: { + float: "right" + } + }, pageSwitchDiv); + + dojo.connect(nextHref, "onclick", this, dojo.partial(function(){ + if(sim.kittens.length - 10 > this.startKitten){ + this.startKitten += 10; + } + this.render(this.container); + })); + //--------------- First Page ----------------- + var firstHref = dojo.create("a", { + href: "#", innerHTML: "<<", + className: "firstHref", + style: { + float: "left" + } + }, pageSwitchDiv); + + dojo.connect(firstHref, "onclick", this, dojo.partial(function(){ + this.startKitten = 0; + this.render(this.container); + })); + //--------------- Previous page ----------------- + var previousHref = dojo.create("a", { + href: "#", innerHTML: $I("village.btn.previous"), + className: "previousHref", + style: { + float: "left" + } + }, pageSwitchDiv); + + dojo.connect(previousHref, "onclick", this, dojo.partial(function(){ + this.startKitten -= 10; + if(this.startKitten < 0){ + this.startKitten = 0; + } + this.render(this.container); + })); + }, makeLeader: function(kitten){ @@ -3644,6 +3850,7 @@ dojo.declare("classes.ui.village.Census", null, { : this.game.village.sim.getSkillsSorted(kitten.skills); var info = ""; + var craftInfo = ""; for (var j = 0; j < Math.min(skillsArr.length,3) ; j++) { @@ -3678,11 +3885,22 @@ dojo.declare("classes.ui.village.Census", null, { bonus = bonus * 100; bonus = bonus > 0 ? " +" + bonus.toFixed(0) + "%" : ""; } + if(kitten.job == "engineer" && j == 0){ + craftInfo = $I("village.census.crafting") + " "; + if (kitten.engineerSpeciality){ + craftInfo += this.game.workshop.getCraft(kitten.engineerSpeciality).label; + } else{ + craftInfo += $I("village.census.crafting.nothing"); + } + } else{ + craftInfo = ""; + } + info += "" + this.game.village.getJob(skillsArr[j].name).title + bonus - + " (" + this.game.villageTab.skillToText(exp) + " " + expPercent.toFixed() + "%)" - + "
"; + + " (" + this.game.villageTab.skillToText(exp) + " " + expPercent.toFixed() + "%) " + + craftInfo + "
"; } return info; @@ -3821,8 +4039,9 @@ dojo.declare("classes.ui.village.Census", null, { record.content.innerHTML += skillInfo; if (!this.game.challenges.isActive("anarchy")) { - record.leaderHref.innerHTML = kitten.isLeader ? "★" : "☆"; //star-shaped link to reduce visual noise + record.leaderHref.innerHTML = kitten.isLeader ? "⚑" : "⚐"; //flag-shaped link to reduce visual noise } + record.favoriteHref.innerHTML = kitten.favorite ? "★" : "☆"; //star-shaped link to reduce visual noise } } diff --git a/res/i18n/en.json b/res/i18n/en.json index bd77335e44..de9f5d7a41 100644 --- a/res/i18n/en.json +++ b/res/i18n/en.json @@ -1865,8 +1865,12 @@ "village.btn.loadout.delete": "X", "village.btn.loadout.delete.confirm": "Are you sure you want to delete the {0} loadout?", "village.btn.loadout.empty": "Empty", - + "village.btn.next": "Next Page", + "village.btn.previous": "Previous Page", + "village.census.age": "years old", + "village.census.crafting": "Crafting: ", + "village.census.crafting.nothing": "Nothing", "village.census.filter.all": "All jobs", "village.census.lbl.festival.duration": "Festival duration", "village.census.lbl.happiness": "Happiness", @@ -1874,6 +1878,10 @@ "village.census.leader.propmote": "Promote ({0} exp, {1} gold)", "village.census.page": "Page {0} of {1}", "village.census.rank": "rank", + "village.census.sort.exp": "Sort by Exp", + "village.census.sort.favorite": "Favorites", + "village.census.sort.color": "Color", + "village.census.sort.variety": "Variety", "village.census.trait.none": "No trait :< ", "village.festival.msg.start": "The cultural festival has started", "village.festival.msg.ext": "The cultural festival has been extended",