Compare commits

...

7 Commits

Author SHA1 Message Date
Flashfyre
8d96ec7666 Add canonical link 2024-05-13 01:43:04 -04:00
Tempoanon
e9c09070df
Stench should not trigger on status moves (#800) 2024-05-13 00:24:07 -05:00
Benjamin Odom
9ee5fec41d
Added Passives to the Summary Screen (#703)
* Added passives to the Summary Screen

Adds the ability to view passives on the Summary screen. Just like in the starter select, you can only see the passive once it is unlocked.

There is a small pixel button prompt which helps indicate you are able to press the button to view the passive. This buttons shows an A when gamepad support is enabled and a Z otherwise.

* Update summary-ui-handler.ts

* Updated for Legacy Support
2024-05-12 23:38:28 -04:00
Samuel H
2b9b63e3f3
Add combined save between waves (#777) 2024-05-12 23:01:05 -04:00
James Diefenbach
9a09d790f0
Rockruff dusk form not evolving (#700)
* changed nonfunctioning rockruff form check to ability check for own tempo for dusk form evos

* testing changes

* rockruff OT uses formIndex for dusk form evolution, removed temporary debug rockruff getFormIndex changes

* reverted overrides

* fixed spacing issue

* evolution times revised

* revised dawn and dusk evos for rockruff

* reordering evo times for consistency

* removed unused imports (abilities, attackTypeBoosterModifierType)

---------

Co-authored-by: James Diefenbach <z5421232@ad.unsw.edu.au>
2024-05-12 22:00:46 -05:00
Xavion3
22097a0c95 Fix getSunday function 2024-05-12 21:22:50 -04:00
Flashfyre
347972d103 Remove boosted shiny rate 2024-05-12 20:45:41 -04:00
19 changed files with 183 additions and 60 deletions

View File

@ -11,6 +11,7 @@
<meta property="og:image" content="https://pokerogue.net/logo512.png" /> <meta property="og:image" content="https://pokerogue.net/logo512.png" />
<link rel="apple-touch-icon" href="./logo512.png" /> <link rel="apple-touch-icon" href="./logo512.png" />
<link rel="shortcut icon" type="image/png" href="./logo512.png" /> <link rel="shortcut icon" type="image/png" href="./logo512.png" />
<link rel="canonical" href="https://pokerogue.net" />
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" /> <meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
<style type="text/css"> <style type="text/css">

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 295 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 310 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 182 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 191 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 295 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 310 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 182 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 191 B

View File

@ -2783,7 +2783,7 @@ export const allAbilities = [ new Ability(Abilities.NONE, 3) ];
export function initAbilities() { export function initAbilities() {
allAbilities.push( allAbilities.push(
new Ability(Abilities.STENCH, 3) new Ability(Abilities.STENCH, 3)
.attr(PostAttackApplyBattlerTagAbAttr, false, (user, target, move) => !move.getMove().findAttr(attr => attr instanceof FlinchAttr) ? 10 : 0, BattlerTagType.FLINCHED), .attr(PostAttackApplyBattlerTagAbAttr, false, (user, target, move) => (move.getMove().category !== MoveCategory.STATUS && !move.getMove().findAttr(attr => attr instanceof FlinchAttr)) ? 10 : 0, BattlerTagType.FLINCHED),
new Ability(Abilities.DRIZZLE, 3) new Ability(Abilities.DRIZZLE, 3)
.attr(PostSummonWeatherChangeAbAttr, WeatherType.RAIN) .attr(PostSummonWeatherChangeAbAttr, WeatherType.RAIN)
.attr(PostBiomeChangeWeatherChangeAbAttr, WeatherType.RAIN), .attr(PostBiomeChangeWeatherChangeAbAttr, WeatherType.RAIN),

View File

@ -1,6 +1,5 @@
import { Gender } from "./gender"; import { Gender } from "./gender";
import { AttackTypeBoosterModifier, FlinchChanceModifier } from "../modifier/modifier"; import { AttackTypeBoosterModifier, FlinchChanceModifier } from "../modifier/modifier";
import { AttackTypeBoosterModifierType } from "../modifier/modifier-type";
import { Moves } from "./enums/moves"; import { Moves } from "./enums/moves";
import { PokeballType } from "./pokeball"; import { PokeballType } from "./pokeball";
import Pokemon from "../field/pokemon"; import Pokemon from "../field/pokemon";
@ -1392,9 +1391,9 @@ export const pokemonEvolutions: PokemonEvolutions = {
new SpeciesEvolution(Species.CRABOMINABLE, 1, EvolutionItem.ICE_STONE, null) new SpeciesEvolution(Species.CRABOMINABLE, 1, EvolutionItem.ICE_STONE, null)
], ],
[Species.ROCKRUFF]: [ [Species.ROCKRUFF]: [
new SpeciesFormEvolution(Species.LYCANROC, '', 'midday', 25, null, new SpeciesEvolutionCondition(p => p.scene.arena.getTimeOfDay() === TimeOfDay.DAY), null), new SpeciesFormEvolution(Species.LYCANROC, '', 'midday', 25, null, new SpeciesEvolutionCondition(p => (p.scene.arena.getTimeOfDay() === TimeOfDay.DAWN || p.scene.arena.getTimeOfDay() === TimeOfDay.DAY) && (p.formIndex === 0)), null),
new SpeciesFormEvolution(Species.LYCANROC, '', 'dusk', 25, null, new SpeciesEvolutionCondition(p => p.scene.getSpeciesFormIndex(p.species) === 1), null), new SpeciesFormEvolution(Species.LYCANROC, '', 'dusk', 25, null, new SpeciesEvolutionCondition(p => p.formIndex === 1), null),
new SpeciesFormEvolution(Species.LYCANROC, '', 'midnight', 25, null, new SpeciesEvolutionCondition(p => p.scene.arena.getTimeOfDay() === TimeOfDay.NIGHT), null) new SpeciesFormEvolution(Species.LYCANROC, '', 'midnight', 25, null, new SpeciesEvolutionCondition(p => (p.scene.arena.getTimeOfDay() === TimeOfDay.DUSK || p.scene.arena.getTimeOfDay() === TimeOfDay.NIGHT) && (p.formIndex === 0)), null)
], ],
[Species.STEENEE]: [ [Species.STEENEE]: [
new SpeciesEvolution(Species.TSAREENA, 28, null, new SpeciesEvolutionCondition(p => p.moveset.filter(m => m.moveId === Moves.STOMP).length > 0), SpeciesWildEvolutionDelay.LONG) new SpeciesEvolution(Species.TSAREENA, 28, null, new SpeciesEvolutionCondition(p => p.moveset.filter(m => m.moveId === Moves.STOMP).length > 0), SpeciesWildEvolutionDelay.LONG)

View File

@ -1096,11 +1096,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
let shinyThreshold = new Utils.IntegerHolder(32); let shinyThreshold = new Utils.IntegerHolder(32);
if (thresholdOverride === undefined) { if (thresholdOverride === undefined) {
if (!this.hasTrainer()) { if (!this.hasTrainer())
if (new Date() < new Date('2024-05-13'))
shinyThreshold.value *= 3;
this.scene.applyModifiers(ShinyRateBoosterModifier, true, shinyThreshold); this.scene.applyModifiers(ShinyRateBoosterModifier, true, shinyThreshold);
}
} else } else
shinyThreshold.value = thresholdOverride; shinyThreshold.value = thresholdOverride;

View File

@ -100,6 +100,10 @@ export class LoadingScene extends SceneBase {
this.loadImage('summary_bg', 'ui'); this.loadImage('summary_bg', 'ui');
this.loadImage('summary_overlay_shiny', 'ui'); this.loadImage('summary_overlay_shiny', 'ui');
this.loadImage('summary_profile', 'ui'); this.loadImage('summary_profile', 'ui');
this.loadImage('summary_profile_prompt_z', 'ui') // The pixel Z button prompt
this.loadImage('summary_profile_prompt_a', 'ui'); // The pixel A button prompt
this.loadImage('summary_profile_ability', 'ui'); // Pixel text 'ABILITY'
this.loadImage('summary_profile_passive', 'ui'); // Pixel text 'PASSIVE'
this.loadImage('summary_status', 'ui'); this.loadImage('summary_status', 'ui');
this.loadImage('summary_stats', 'ui'); this.loadImage('summary_stats', 'ui');
this.loadImage('summary_stats_overlay_exp', 'ui'); this.loadImage('summary_stats_overlay_exp', 'ui');

View File

@ -775,11 +775,11 @@ export class EncounterPhase extends BattlePhase {
this.scene.ui.setMode(Mode.MESSAGE).then(() => { this.scene.ui.setMode(Mode.MESSAGE).then(() => {
if (!this.loaded) { if (!this.loaded) {
this.scene.gameData.saveSystem().then(success => { this.scene.gameData.saveAll(this.scene, true).then(success => {
this.scene.disableMenu = false; this.scene.disableMenu = false;
if (!success) if (!success)
return this.scene.reset(true); return this.scene.reset(true);
this.scene.gameData.saveSession(this.scene, true).then(() => this.doEncounter()); this.doEncounter();
}); });
} else } else
this.doEncounter(); this.doEncounter();

View File

@ -250,24 +250,28 @@ export class GameData {
this.initStarterData(); this.initStarterData();
} }
public getSystemSaveData(): SystemSaveData {
return {
trainerId: this.trainerId,
secretId: this.secretId,
gender: this.gender,
dexData: this.dexData,
starterData: this.starterData,
gameStats: this.gameStats,
unlocks: this.unlocks,
achvUnlocks: this.achvUnlocks,
voucherUnlocks: this.voucherUnlocks,
voucherCounts: this.voucherCounts,
eggs: this.eggs.map(e => new EggData(e)),
gameVersion: this.scene.game.config.gameVersion,
timestamp: new Date().getTime()
};
}
public saveSystem(): Promise<boolean> { public saveSystem(): Promise<boolean> {
return new Promise<boolean>(resolve => { return new Promise<boolean>(resolve => {
this.scene.ui.savingIcon.show(); this.scene.ui.savingIcon.show();
const data: SystemSaveData = { const data = this.getSystemSaveData();
trainerId: this.trainerId,
secretId: this.secretId,
gender: this.gender,
dexData: this.dexData,
starterData: this.starterData,
gameStats: this.gameStats,
unlocks: this.unlocks,
achvUnlocks: this.achvUnlocks,
voucherUnlocks: this.voucherUnlocks,
voucherCounts: this.voucherCounts,
eggs: this.eggs.map(e => new EggData(e)),
gameVersion: this.scene.game.config.gameVersion,
timestamp: new Date().getTime()
};
const maxIntAttrValue = Math.pow(2, 31); const maxIntAttrValue = Math.pow(2, 31);
const systemData = JSON.stringify(data, (k: any, v: any) => typeof v === 'bigint' ? v <= maxIntAttrValue ? Number(v) : v.toString() : v); const systemData = JSON.stringify(data, (k: any, v: any) => typeof v === 'bigint' ? v <= maxIntAttrValue ? Number(v) : v.toString() : v);
@ -817,6 +821,59 @@ export class GameData {
}) as SessionSaveData; }) as SessionSaveData;
} }
saveAll(scene: BattleScene, skipVerification?: boolean): Promise<boolean> {
return new Promise<boolean>(resolve => {
Utils.executeIf(!skipVerification, updateUserInfo).then(success => {
if (success !== null && !success)
return resolve(false);
this.scene.ui.savingIcon.show();
const data = this.getSystemSaveData();
const sessionData = this.getSessionSaveData(scene);
const maxIntAttrValue = Math.pow(2, 31);
const systemData = this.getSystemSaveData();
const request = {
system: systemData,
session: sessionData,
sessionSlotId: scene.sessionSlotId
};
if (!bypassLogin) {
Utils.apiPost('savedata/updateall', JSON.stringify(request, (k: any, v: any) => typeof v === 'bigint' ? v <= maxIntAttrValue ? Number(v) : v.toString() : v), undefined, true)
.then(response => response.text())
.then(error => {
this.scene.ui.savingIcon.hide();
if (error) {
if (error.startsWith('client version out of date')) {
this.scene.clearPhaseQueue();
this.scene.unshiftPhase(new OutdatedPhase(this.scene));
} else if (error.startsWith('session out of date')) {
this.scene.clearPhaseQueue();
this.scene.unshiftPhase(new ReloadSessionPhase(this.scene));
}
console.error(error);
return resolve(false);
}
resolve(true);
});
} else {
localStorage.setItem('data_bak', localStorage.getItem('data'));
localStorage.setItem('data', btoa(JSON.stringify(systemData, (k: any, v: any) => typeof v === 'bigint' ? v <= maxIntAttrValue ? Number(v) : v.toString() : v)));
localStorage.setItem(`sessionData${scene.sessionSlotId ? scene.sessionSlotId : ''}`, btoa(JSON.stringify(sessionData)));
console.debug('Session data saved');
this.scene.ui.savingIcon.hide();
resolve(true);
}
});
});
}
public tryExportData(dataType: GameDataType, slotId: integer = 0): Promise<boolean> { public tryExportData(dataType: GameDataType, slotId: integer = 0): Promise<boolean> {
return new Promise<boolean>(resolve => { return new Promise<boolean>(resolve => {
const dataKey: string = getDataTypeKey(dataType, slotId); const dataKey: string = getDataTypeKey(dataType, slotId);

View File

@ -20,6 +20,7 @@ import { loggedInUser } from "../account";
import { PlayerGender } from "../system/game-data"; import { PlayerGender } from "../system/game-data";
import { Variant, getVariantTint } from "#app/data/variant"; import { Variant, getVariantTint } from "#app/data/variant";
import {Button} from "../enums/buttons"; import {Button} from "../enums/buttons";
import { Ability } from "../data/ability.js";
enum Page { enum Page {
PROFILE, PROFILE,
@ -32,6 +33,18 @@ export enum SummaryUiMode {
LEARN_MOVE LEARN_MOVE
} }
/** Holds all objects related to an ability for each iteration */
interface abilityContainer {
/** An image displaying the summary label */
labelImage: Phaser.GameObjects.Image,
/** The ability object */
ability: Ability,
/** The text object displaying the name of the ability */
nameText: Phaser.GameObjects.Text,
/** The text object displaying the description of the ability */
descriptionText: Phaser.GameObjects.Text,
}
export default class SummaryUiHandler extends UiHandler { export default class SummaryUiHandler extends UiHandler {
private summaryUiMode: SummaryUiMode; private summaryUiMode: SummaryUiMode;
@ -54,6 +67,12 @@ export default class SummaryUiHandler extends UiHandler {
private championRibbon: Phaser.GameObjects.Image; private championRibbon: Phaser.GameObjects.Image;
private statusContainer: Phaser.GameObjects.Container; private statusContainer: Phaser.GameObjects.Container;
private status: Phaser.GameObjects.Image; private status: Phaser.GameObjects.Image;
/** The pixel button prompt indicating a passive is unlocked */
private abilityPrompt: Phaser.GameObjects.Image;
/** Object holding everything needed to display an ability */
private abilityContainer: abilityContainer;
/** Object holding everything needed to display a passive */
private passiveContainer: abilityContainer;
private summaryPageContainer: Phaser.GameObjects.Container; private summaryPageContainer: Phaser.GameObjects.Container;
private movesContainer: Phaser.GameObjects.Container; private movesContainer: Phaser.GameObjects.Container;
private moveDescriptionText: Phaser.GameObjects.Text; private moveDescriptionText: Phaser.GameObjects.Text;
@ -441,6 +460,17 @@ export default class SummaryUiHandler extends UiHandler {
this.showMoveSelect(); this.showMoveSelect();
success = true; success = true;
} }
// if we're on the PROFILE page and this pokemon has a passive unlocked..
else if (this.cursor === Page.PROFILE && this.pokemon.hasPassive()) {
// Since abilities are displayed by default, all we need to do is toggle visibility on all elements to show passives
this.abilityContainer.nameText.setVisible(!this.abilityContainer.descriptionText.visible);
this.abilityContainer.descriptionText.setVisible(!this.abilityContainer.descriptionText.visible);
this.abilityContainer.labelImage.setVisible(!this.abilityContainer.labelImage.visible);
this.passiveContainer.nameText.setVisible(!this.passiveContainer.descriptionText.visible);
this.passiveContainer.descriptionText.setVisible(!this.passiveContainer.descriptionText.visible);
this.passiveContainer.labelImage.setVisible(!this.passiveContainer.labelImage.visible);
}
} else if (button === Button.CANCEL) { } else if (button === Button.CANCEL) {
if (this.summaryUiMode === SummaryUiMode.LEARN_MOVE) if (this.summaryUiMode === SummaryUiMode.LEARN_MOVE)
this.hideMoveSelect(); this.hideMoveSelect();
@ -686,40 +716,75 @@ export default class SummaryUiHandler extends UiHandler {
profileContainer.add(luckText); profileContainer.add(luckText);
} }
const ability = this.pokemon.getAbility(true); this.abilityContainer = {
labelImage: this.scene.add.image(0, 0, 'summary_profile_ability'),
ability: this.pokemon.getAbility(true),
nameText: null,
descriptionText: null};
const abilityNameText = addTextObject(this.scene, 7, 66, ability.name, TextStyle.SUMMARY_ALT); const allAbilityInfo = [this.abilityContainer]; // Creates an array to iterate through
abilityNameText.setOrigin(0, 1); // Only add to the array and set up displaying a passive if it's unlocked
profileContainer.add(abilityNameText); if (this.pokemon.hasPassive()) {
this.passiveContainer = {
labelImage: this.scene.add.image(0, 0, 'summary_profile_passive'),
ability: this.pokemon.getPassiveAbility(),
nameText: null,
descriptionText: null};
allAbilityInfo.push(this.passiveContainer);
const abilityDescriptionText = addTextObject(this.scene, 7, 69, ability.description, TextStyle.WINDOW_ALT, { wordWrap: { width: 1224 } }); // Sets up the pixel button prompt image
abilityDescriptionText.setOrigin(0, 0); this.abilityPrompt = this.scene.add.image(0, 0, !this.scene.gamepadSupport ? 'summary_profile_prompt_z' : 'summary_profile_prompt_a');
profileContainer.add(abilityDescriptionText); this.abilityPrompt.setPosition(8, 43);
this.abilityPrompt.setVisible(true);
const abilityDescriptionTextMaskRect = this.scene.make.graphics({}); this.abilityPrompt.setOrigin(0, 0);
abilityDescriptionTextMaskRect.setScale(6); profileContainer.add(this.abilityPrompt);
abilityDescriptionTextMaskRect.fillStyle(0xFFFFFF);
abilityDescriptionTextMaskRect.beginPath();
abilityDescriptionTextMaskRect.fillRect(110, 90.5, 206, 31);
const abilityDescriptionTextMask = abilityDescriptionTextMaskRect.createGeometryMask();
abilityDescriptionText.setMask(abilityDescriptionTextMask);
const abilityDescriptionLineCount = Math.floor(abilityDescriptionText.displayHeight / 14.83);
if (abilityDescriptionLineCount > 2) {
abilityDescriptionText.setY(69);
this.descriptionScrollTween = this.scene.tweens.add({
targets: abilityDescriptionText,
delay: Utils.fixedInt(2000),
loop: -1,
hold: Utils.fixedInt(2000),
duration: Utils.fixedInt((abilityDescriptionLineCount - 2) * 2000),
y: `-=${14.83 * (abilityDescriptionLineCount - 2)}`
});
} }
allAbilityInfo.forEach(abilityInfo => {
abilityInfo.labelImage.setPosition(17, 43);
abilityInfo.labelImage.setVisible(true);
abilityInfo.labelImage.setOrigin(0, 0);
profileContainer.add(abilityInfo.labelImage);
abilityInfo.nameText = addTextObject(this.scene, 7, 66, abilityInfo.ability.name, TextStyle.SUMMARY_ALT);
abilityInfo.nameText.setOrigin(0, 1);
profileContainer.add(abilityInfo.nameText);
abilityInfo.descriptionText = addTextObject(this.scene, 7, 69, abilityInfo.ability.description, TextStyle.WINDOW_ALT, { wordWrap: { width: 1224 } });
abilityInfo.descriptionText.setOrigin(0, 0);
profileContainer.add(abilityInfo.descriptionText);
// Sets up the mask that hides the description text to give an illusion of scrolling
const descriptionTextMaskRect = this.scene.make.graphics({});
descriptionTextMaskRect.setScale(6);
descriptionTextMaskRect.fillStyle(0xFFFFFF);
descriptionTextMaskRect.beginPath();
descriptionTextMaskRect.fillRect(110, 90.5, 206, 31);
const abilityDescriptionTextMask = descriptionTextMaskRect.createGeometryMask();
abilityInfo.descriptionText.setMask(abilityDescriptionTextMask);
const abilityDescriptionLineCount = Math.floor(abilityInfo.descriptionText.displayHeight / 14.83);
// Animates the description text moving upwards
if (abilityDescriptionLineCount > 2) {
abilityInfo.descriptionText.setY(69);
this.descriptionScrollTween = this.scene.tweens.add({
targets: abilityInfo.descriptionText,
delay: Utils.fixedInt(2000),
loop: -1,
hold: Utils.fixedInt(2000),
duration: Utils.fixedInt((abilityDescriptionLineCount - 2) * 2000),
y: `-=${14.83 * (abilityDescriptionLineCount - 2)}`
});
}
});
// Turn off visibility of passive info by default
this.passiveContainer?.labelImage.setVisible(false);
this.passiveContainer?.nameText.setVisible(false);
this.passiveContainer?.descriptionText.setVisible(false);
let memoString = `${getBBCodeFrag(Utils.toReadableString(Nature[this.pokemon.getNature()]), TextStyle.SUMMARY_RED)}${getBBCodeFrag(' nature,', TextStyle.WINDOW_ALT)}\n${getBBCodeFrag(`${this.pokemon.metBiome === -1 ? 'apparently ' : ''}met at Lv`, TextStyle.WINDOW_ALT)}${getBBCodeFrag(this.pokemon.metLevel.toString(), TextStyle.SUMMARY_RED)}${getBBCodeFrag(',', TextStyle.WINDOW_ALT)}\n${getBBCodeFrag(getBiomeName(this.pokemon.metBiome), TextStyle.SUMMARY_RED)}${getBBCodeFrag('.', TextStyle.WINDOW_ALT)}`; let memoString = `${getBBCodeFrag(Utils.toReadableString(Nature[this.pokemon.getNature()]), TextStyle.SUMMARY_RED)}${getBBCodeFrag(' nature,', TextStyle.WINDOW_ALT)}\n${getBBCodeFrag(`${this.pokemon.metBiome === -1 ? 'apparently ' : ''}met at Lv`, TextStyle.WINDOW_ALT)}${getBBCodeFrag(this.pokemon.metLevel.toString(), TextStyle.SUMMARY_RED)}${getBBCodeFrag(',', TextStyle.WINDOW_ALT)}\n${getBBCodeFrag(getBiomeName(this.pokemon.metBiome), TextStyle.SUMMARY_RED)}${getBBCodeFrag('.', TextStyle.WINDOW_ALT)}`;
const memoText = addBBCodeTextObject(this.scene, 7, 113, memoString, TextStyle.WINDOW_ALT); const memoText = addBBCodeTextObject(this.scene, 7, 113, memoString, TextStyle.WINDOW_ALT);

View File

@ -117,9 +117,9 @@ export function randSeedEasedWeightedItem<T>(items: T[], easingFunction: string
} }
export function getSunday(date: Date): Date { export function getSunday(date: Date): Date {
const day = date.getDay(); const day = date.getUTCDay();
const diff = date.getDate() - day; const diff = date.getUTCDate() - day;
const newDate = new Date(date.setDate(diff)); const newDate = new Date(date.setUTCDate(diff));
return new Date(Date.UTC(newDate.getUTCFullYear(), newDate.getUTCMonth(), newDate.getUTCDate())); return new Date(Date.UTC(newDate.getUTCFullYear(), newDate.getUTCMonth(), newDate.getUTCDate()));
} }