v2.3.0: rewrote internal holiday logic

This commit is contained in:
Evan Debenham
2023-11-22 14:06:58 -05:00
parent 3d7b25e7e5
commit 1dae6f108f
5 changed files with 254 additions and 62 deletions

View File

@@ -30,6 +30,7 @@ import com.shatteredpixel.shatteredpixeldungeon.items.KingsCrown;
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
import com.shatteredpixel.shatteredpixeldungeon.sprites.RatKingSprite;
import com.shatteredpixel.shatteredpixeldungeon.utils.Holiday;
import com.shatteredpixel.shatteredpixeldungeon.windows.WndInfoArmorAbility;
import com.shatteredpixel.shatteredpixeldungeon.windows.WndOptions;
import com.watabou.noosa.Game;
@@ -160,8 +161,10 @@ public class RatKing extends NPC {
@Override
public String description() {
return ((RatKingSprite)sprite).festive ?
Messages.get(this, "desc_festive")
: super.description();
if (Holiday.getCurrentHoliday() == Holiday.WINTER_HOLIDAYS){
return Messages.get(this, "desc_festive");
} else {
return super.description();
}
}
}

View File

@@ -29,47 +29,10 @@ import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfRecharging;
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
import java.util.Calendar;
import com.shatteredpixel.shatteredpixeldungeon.utils.Holiday;
public class Pasty extends Food {
//TODO: implement fun stuff for other holidays
//TODO: probably should externalize this if I want to add any more festive stuff.
private enum Holiday{
NONE,
EASTER, //TBD
HWEEN,//2nd week of october though first day of november
XMAS //3rd week of december through first week of january
}
private static Holiday holiday;
static{
holiday = Holiday.NONE;
final Calendar calendar = Calendar.getInstance();
switch(calendar.get(Calendar.MONTH)){
case Calendar.JANUARY:
if (calendar.get(Calendar.WEEK_OF_MONTH) == 1)
holiday = Holiday.XMAS;
break;
case Calendar.OCTOBER:
if (calendar.get(Calendar.WEEK_OF_MONTH) >= 2)
holiday = Holiday.HWEEN;
break;
case Calendar.NOVEMBER:
if (calendar.get(Calendar.DAY_OF_MONTH) == 1)
holiday = Holiday.HWEEN;
break;
case Calendar.DECEMBER:
if (calendar.get(Calendar.WEEK_OF_MONTH) >= 3)
holiday = Holiday.XMAS;
break;
}
}
{
reset();
@@ -81,14 +44,14 @@ public class Pasty extends Food {
@Override
public void reset() {
super.reset();
switch(holiday){
switch(Holiday.getCurrentHoliday()){
case NONE:
image = ItemSpriteSheet.PASTY;
break;
case HWEEN:
case HALLOWEEN:
image = ItemSpriteSheet.PUMPKIN_PIE;
break;
case XMAS:
case WINTER_HOLIDAYS:
image = ItemSpriteSheet.CANDY_CANE;
break;
}
@@ -98,15 +61,15 @@ public class Pasty extends Food {
protected void satisfy(Hero hero) {
super.satisfy(hero);
switch(holiday){
case NONE:
switch(Holiday.getCurrentHoliday()){
default:
break; //do nothing extra
case HWEEN:
case HALLOWEEN:
//heals for 10% max hp
hero.HP = Math.min(hero.HP + hero.HT/10, hero.HT);
hero.sprite.emitter().burst( Speck.factory( Speck.HEALING ), 1 );
break;
case XMAS:
case WINTER_HOLIDAYS:
Buff.affect( hero, Recharging.class, 2f ); //half of a charge
ScrollOfRecharging.charge( hero );
break;
@@ -115,24 +78,24 @@ public class Pasty extends Food {
@Override
public String name() {
switch(holiday){
switch(Holiday.getCurrentHoliday()){
case NONE: default:
return Messages.get(this, "pasty");
case HWEEN:
case HALLOWEEN:
return Messages.get(this, "pie");
case XMAS:
case WINTER_HOLIDAYS:
return Messages.get(this, "cane");
}
}
@Override
public String info() {
switch(holiday){
switch(Holiday.getCurrentHoliday()){
case NONE: default:
return Messages.get(this, "pasty_desc");
case HWEEN:
case HALLOWEEN:
return Messages.get(this, "pie_desc");
case XMAS:
case WINTER_HOLIDAYS:
return Messages.get(this, "cane_desc");
}
}

View File

@@ -31,6 +31,7 @@ import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
import com.shatteredpixel.shatteredpixeldungeon.ui.RenderedTextBlock;
import com.shatteredpixel.shatteredpixeldungeon.ui.Tooltip;
import com.shatteredpixel.shatteredpixeldungeon.ui.Window;
import com.shatteredpixel.shatteredpixeldungeon.utils.Holiday;
import com.watabou.gltextures.TextureCache;
import com.watabou.glwrap.Blending;
import com.watabou.input.ControllerHandler;
@@ -99,6 +100,8 @@ public class PixelScene extends Scene {
if (!inGameScene && InterlevelScene.lastRegion != -1){
InterlevelScene.lastRegion = -1;
TextureCache.clear();
//good time to clear holiday cache as well
Holiday.clearCachedHoliday();
}
float minWidth, minHeight, scaleFactor;

View File

@@ -25,10 +25,9 @@ import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.abilities.Ratmogrify;
import com.shatteredpixel.shatteredpixeldungeon.utils.Holiday;
import com.watabou.noosa.TextureFilm;
import java.util.Calendar;
public class RatKingSprite extends MobSprite {
public boolean festive;
@@ -41,12 +40,7 @@ public class RatKingSprite extends MobSprite {
public void resetAnims(){
final Calendar calendar = Calendar.getInstance();
//once a year the rat king feels a bit festive!
festive = (calendar.get(Calendar.MONTH) == Calendar.DECEMBER
&& calendar.get(Calendar.WEEK_OF_MONTH) > 2);
int c = festive ? 8 : 0;
int c = Holiday.getCurrentHoliday() == Holiday.WINTER_HOLIDAYS ? 8 : 0;
if (Dungeon.hero != null && Dungeon.hero.armorAbility instanceof Ratmogrify){
c += 16;

View File

@@ -0,0 +1,229 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2015 Oleg Dolya
*
* Shattered Pixel Dungeon
* Copyright (C) 2014-2023 Evan Debenham
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.utils;
import java.util.Calendar;
import java.util.GregorianCalendar;
public enum Holiday {
NONE,
//TODO many of these don't actually do anything atm
LUNAR_NEW_YEAR, //Varies, sometime in late Jan to Late Feb (7 days)
APRIL_FOOLS, //April 1st, can override easter (1 day)
EASTER, //Varies, sometime in Late Mar to Late Apr (6-7 days)
//Nothing in May
PRIDE, //Jun 24th to Jun 30th (7 days)
//Nothing in Jul
SHATTEREDPD_BIRTHDAY, //Aug 1st to Aug 7th (7 days)
//Nothing in Sept
HALLOWEEN, //Oct 24th to Oct 31st (7 days)
//Nothing in Nov
PD_BIRTHDAY, //Dec 1st to Dec 7th (7 days)
WINTER_HOLIDAYS, //Dec 15th to Dec 26th (12 days)
NEW_YEARS; //Dec 27th to Jan 2nd (7 days)
//total of 61-62 festive days each year, mainly concentrated in Late Oct to Early Feb
//we cache the holiday here so that holiday logic doesn't suddenly shut off mid-game
//this gets cleared on game launch (of course), and whenever leaving a game scene
private static Holiday cached;
public static void clearCachedHoliday(){
cached = null;
}
public static Holiday getCurrentHoliday(){
return getHolidayForDate((GregorianCalendar) GregorianCalendar.getInstance());
}
//requires a gregorian calendar
public static Holiday getHolidayForDate(GregorianCalendar cal){
if (cached != null){
return cached;
}
//legacy holiday logic from late 2016 to early 2024
//only halloween and winter holidays, and they had longer dates determined by week of month
//TODO maybe remove this after early 2024 passes?
// Do we really care about historical accuracy for folks who turn their system date back?
if (cal.get(Calendar.YEAR) < 2024
|| (cal.get(Calendar.YEAR) == 2024 && cal.get(Calendar.DAY_OF_YEAR) <= 10)){
switch(cal.get(Calendar.MONTH)){
case Calendar.JANUARY:
if (cal.get(Calendar.WEEK_OF_MONTH) == 1)
return WINTER_HOLIDAYS;
break;
case Calendar.OCTOBER:
if (cal.get(Calendar.WEEK_OF_MONTH) >= 2)
return HALLOWEEN;
break;
case Calendar.NOVEMBER:
if (cal.get(Calendar.DAY_OF_MONTH) == 1)
return HALLOWEEN;
break;
case Calendar.DECEMBER:
if (cal.get(Calendar.WEEK_OF_MONTH) >= 3)
return WINTER_HOLIDAYS;
break;
}
}
//Lunar New Year
if (isLunarNewYear(cal.get(Calendar.YEAR),
cal.get(Calendar.DAY_OF_YEAR))){
return LUNAR_NEW_YEAR;
}
//April Fools
if (cal.get(Calendar.MONTH) == Calendar.APRIL
&& cal.get(Calendar.DAY_OF_MONTH) == 1){
return APRIL_FOOLS;
}
//Easter
if (isEaster(cal.get(Calendar.YEAR),
cal.get(Calendar.DAY_OF_YEAR),
cal.getActualMaximum(Calendar.DAY_OF_YEAR) == 366)){
return EASTER;
}
//Pride
if (cal.get(Calendar.MONTH) == Calendar.JUNE
&& cal.get(Calendar.DAY_OF_MONTH) >= 24){
return PRIDE;
}
//Shattered's Birthday
if (cal.get(Calendar.MONTH) == Calendar.AUGUST
&& cal.get(Calendar.DAY_OF_MONTH) <= 7){
return SHATTEREDPD_BIRTHDAY;
}
//Halloween
if (cal.get(Calendar.MONTH) == Calendar.OCTOBER
&& cal.get(Calendar.DAY_OF_MONTH) >= 24){
return HALLOWEEN;
}
//Pixel Dungeon's Birthday
if (cal.get(Calendar.MONTH) == Calendar.DECEMBER
&& cal.get(Calendar.DAY_OF_MONTH) <= 7){
return PD_BIRTHDAY;
}
//Winter Holidays
if (cal.get(Calendar.MONTH) == Calendar.DECEMBER
&& cal.get(Calendar.DAY_OF_MONTH) >= 15
&& cal.get(Calendar.DAY_OF_MONTH) <= 26){
return WINTER_HOLIDAYS;
}
//New Years
if ((cal.get(Calendar.MONTH) == Calendar.DECEMBER && cal.get(Calendar.DAY_OF_MONTH) >= 27)
|| (cal.get(Calendar.MONTH) == Calendar.JANUARY && cal.get(Calendar.DAY_OF_MONTH) <= 2)){
return NEW_YEARS;
}
return NONE;
}
//has to be hard-coded on a per-year basis =S
public static boolean isLunarNewYear(int year, int dayOfYear){
int lunarNewYearDayOfYear;
switch (year){
//yes, I really did hardcode this all the way to 2050
default: lunarNewYearDayOfYear = 31+3; break; //defaults to February 3rd
case 2024: lunarNewYearDayOfYear = 31+10; break; //February 10th
case 2025: lunarNewYearDayOfYear = 29; break; //January 29th
case 2026: lunarNewYearDayOfYear = 31+17; break; //February 17th
case 2027: lunarNewYearDayOfYear = 31+6; break; //February 6th
case 2028: lunarNewYearDayOfYear = 26; break; //January 26th
case 2029: lunarNewYearDayOfYear = 31+13; break; //February 13th
case 2030: lunarNewYearDayOfYear = 31+3; break; //February 3rd
case 2031: lunarNewYearDayOfYear = 23; break; //January 23rd
case 2032: lunarNewYearDayOfYear = 31+11; break; //February 11th
case 2033: lunarNewYearDayOfYear = 31; break; //January 31st
case 2034: lunarNewYearDayOfYear = 31+19; break; //February 19th
case 2035: lunarNewYearDayOfYear = 31+8; break; //February 8th
case 2036: lunarNewYearDayOfYear = 28; break; //January 28th
case 2037: lunarNewYearDayOfYear = 31+15; break; //February 15th
case 2038: lunarNewYearDayOfYear = 31+4; break; //February 4th
case 2039: lunarNewYearDayOfYear = 24; break; //January 24th
case 2040: lunarNewYearDayOfYear = 31+12; break; //February 12th
case 2041: lunarNewYearDayOfYear = 31+1; break; //February 1st
case 2042: lunarNewYearDayOfYear = 22; break; //January 22nd
case 2043: lunarNewYearDayOfYear = 31+10; break; //February 10th
case 2044: lunarNewYearDayOfYear = 30; break; //January 30th
case 2045: lunarNewYearDayOfYear = 31+17; break; //February 17th
case 2046: lunarNewYearDayOfYear = 31+6; break; //February 6th
case 2047: lunarNewYearDayOfYear = 26; break; //January 26th
case 2048: lunarNewYearDayOfYear = 31+14; break; //February 14th
case 2049: lunarNewYearDayOfYear = 31+2; break; //February 2nd
case 2050: lunarNewYearDayOfYear = 23; break; //January 23rd
}
//celebrate for 7 days total, with actual lunar new year on the 5th day
return dayOfYear >= lunarNewYearDayOfYear-4 && dayOfYear <= lunarNewYearDayOfYear+2;
}
//has to be algorithmically computed =S
public static boolean isEaster(int year, int dayOfYear, boolean isLeapYear){
//if we're not in March or April, just skip out of all these calculations
if (dayOfYear < 59 || dayOfYear > 121) {
return false;
}
//Uses the Anonymous Gregorian Algorithm
int a = year % 19;
int b = year / 100;
int c = year % 100;
int d = b / 4;
int e = b % 4;
int f = (b + 8) / 25;
int g = (b - f + 1) / 3;
int h = (a*19 + b - d - g + 15) % 30;
int i = c / 4;
int k = c % 4;
int l = (32 + 2*e + 2*i - h - k) % 7;
int m = (a + h*11 + l*22)/451;
int n = (h + l - m*7 + 114) / 31;
int o = (h + l - m*7 + 114) % 31;
int easterDayOfYear = 0;
if (n == 3){
easterDayOfYear += 59; //march
} else {
easterDayOfYear += 90; //april
}
if (isLeapYear) {
easterDayOfYear += 1; //add an extra day to account for February 29th
}
easterDayOfYear += (o+1); //add day of month
return dayOfYear >= easterDayOfYear-4 && dayOfYear <= easterDayOfYear+2;
}
}