Add event dates to time_season: easter, halloween, xmas

Add easter, halloween and xmas to `enum ETimeSeason` and `time_season` function. This unifies the logic for detecting these events and seasons in one function. This allows adding support for special easter, halloween and xmas theme maps in the future. The `localtime` function is not used outside `system.c` anymore. The code for detecting easter is taken from upstream.
This commit is contained in:
Robert Müller 2023-10-20 22:16:35 +02:00
parent 28f4739e46
commit e66fe2c70e
5 changed files with 62 additions and 22 deletions

View file

@ -2669,18 +2669,58 @@ int time_houroftheday()
return time_info->tm_hour; return time_info->tm_hour;
} }
int time_season() static bool time_iseasterday(time_t time_data, struct tm *time_info)
{
// compute Easter day (Sunday) using https://en.wikipedia.org/w/index.php?title=Computus&oldid=890710285#Anonymous_Gregorian_algorithm
int Y = time_info->tm_year + 1900;
int a = Y % 19;
int b = Y / 100;
int c = Y % 100;
int d = b / 4;
int e = b % 4;
int f = (b + 8) / 25;
int g = (b - f + 1) / 3;
int h = (19 * a + 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 + 11 * h + 22 * L) / 451;
int month = (h + L - 7 * m + 114) / 31;
int day = ((h + L - 7 * m + 114) % 31) + 1;
// (now-1d ≤ easter ≤ now+2d) <=> (easter-2d ≤ now ≤ easter+1d) <=> (Good Friday ≤ now ≤ Easter Monday)
for(int day_offset = -1; day_offset <= 2; day_offset++)
{
time_data = time_data + day_offset * 60 * 60 * 24;
time_info = localtime(&time_data);
if(time_info->tm_mon == month - 1 && time_info->tm_mday == day)
return true;
}
return false;
}
ETimeSeason time_season()
{ {
time_t time_data; time_t time_data;
struct tm *time_info;
time(&time_data); time(&time_data);
time_info = localtime(&time_data); struct tm *time_info = localtime(&time_data);
if((time_info->tm_mon == 11 && time_info->tm_mday == 31) || (time_info->tm_mon == 0 && time_info->tm_mday == 1)) if((time_info->tm_mon == 11 && time_info->tm_mday == 31) || (time_info->tm_mon == 0 && time_info->tm_mday == 1))
{ {
return SEASON_NEWYEAR; return SEASON_NEWYEAR;
} }
else if(time_info->tm_mon == 11 && time_info->tm_mday >= 24 && time_info->tm_mday <= 26)
{
return SEASON_XMAS;
}
else if((time_info->tm_mon == 9 && time_info->tm_mday == 31) || (time_info->tm_mon == 10 && time_info->tm_mday == 1))
{
return SEASON_HALLOWEEN;
}
else if(time_iseasterday(time_data, time_info))
{
return SEASON_EASTER;
}
switch(time_info->tm_mon) switch(time_info->tm_mon)
{ {
@ -2700,8 +2740,10 @@ int time_season()
case 9: case 9:
case 10: case 10:
return SEASON_AUTUMN; return SEASON_AUTUMN;
default:
dbg_assert(false, "Invalid month");
dbg_break();
} }
return SEASON_SPRING; // should never happen
} }
void str_append(char *dst, const char *src, int dst_size) void str_append(char *dst, const char *src, int dst_size)

View file

@ -803,12 +803,15 @@ int time_houroftheday();
/** /**
* @ingroup Time * @ingroup Time
*/ */
enum enum ETimeSeason
{ {
SEASON_SPRING = 0, SEASON_SPRING = 0,
SEASON_SUMMER, SEASON_SUMMER,
SEASON_AUTUMN, SEASON_AUTUMN,
SEASON_WINTER, SEASON_WINTER,
SEASON_EASTER,
SEASON_HALLOWEEN,
SEASON_XMAS,
SEASON_NEWYEAR SEASON_NEWYEAR
}; };
@ -821,7 +824,7 @@ enum
* *
* @see SEASON_SPRING * @see SEASON_SPRING
*/ */
int time_season(); ETimeSeason time_season();
/** /**
* @defgroup Network-General * @defgroup Network-General

View file

@ -212,15 +212,18 @@ void CMenuBackground::LoadMenuBackground(bool HasDayHint, bool HasNightHint)
switch(time_season()) switch(time_season())
{ {
case SEASON_SPRING: case SEASON_SPRING:
case SEASON_EASTER:
pMenuMap = "heavens"; pMenuMap = "heavens";
break; break;
case SEASON_SUMMER: case SEASON_SUMMER:
pMenuMap = "jungle"; pMenuMap = "jungle";
break; break;
case SEASON_AUTUMN: case SEASON_AUTUMN:
case SEASON_HALLOWEEN:
pMenuMap = "autumn"; pMenuMap = "autumn";
break; break;
case SEASON_WINTER: case SEASON_WINTER:
case SEASON_XMAS:
pMenuMap = "winter"; pMenuMap = "winter";
break; break;
case SEASON_NEWYEAR: case SEASON_NEWYEAR:

View file

@ -3,7 +3,6 @@
#include <base/math.h> #include <base/math.h>
#include <base/system.h> #include <base/system.h>
#include <ctime>
#include <engine/engine.h> #include <engine/engine.h>
#include <engine/graphics.h> #include <engine/graphics.h>
@ -299,12 +298,8 @@ void CSkins::OnInit()
if(g_Config.m_Events) if(g_Config.m_Events)
{ {
time_t RawTime; if(time_season() == SEASON_XMAS)
struct tm *pTimeInfo; {
std::time(&RawTime);
pTimeInfo = localtime(&RawTime);
if(pTimeInfo->tm_mon == 11 && pTimeInfo->tm_mday >= 24 && pTimeInfo->tm_mday <= 26)
{ // Christmas
str_copy(m_aEventSkinPrefix, "santa"); str_copy(m_aEventSkinPrefix, "santa");
} }
} }

View file

@ -87,16 +87,13 @@ void CPlayer::Reset()
if(g_Config.m_Events) if(g_Config.m_Events)
{ {
time_t RawTime; const ETimeSeason Season = time_season();
struct tm *pTimeInfo; if(Season == SEASON_NEWYEAR)
time(&RawTime); {
pTimeInfo = localtime(&RawTime);
if((pTimeInfo->tm_mon == 11 && pTimeInfo->tm_mday == 31) || (pTimeInfo->tm_mon == 0 && pTimeInfo->tm_mday == 1))
{ // New Year
m_DefEmote = EMOTE_HAPPY; m_DefEmote = EMOTE_HAPPY;
} }
else if((pTimeInfo->tm_mon == 9 && pTimeInfo->tm_mday == 31) || (pTimeInfo->tm_mon == 10 && pTimeInfo->tm_mday == 1)) else if(Season == SEASON_HALLOWEEN)
{ // Halloween {
m_DefEmote = EMOTE_ANGRY; m_DefEmote = EMOTE_ANGRY;
m_Halloween = true; m_Halloween = true;
} }