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;
}
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;
struct tm *time_info;
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))
{
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)
{
@ -2700,8 +2740,10 @@ int time_season()
case 9:
case 10:
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)

View file

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

View file

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

View file

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

View file

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