Extended TimeLimit format (quest DB) (#8116)

This commit is contained in:
Atemo 2024-03-25 19:09:31 +01:00 committed by GitHub
parent 42bd87d9b7
commit ed2d03d811
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 69 additions and 14 deletions

View File

@ -20,11 +20,30 @@ Title: Quest title.
TimeLimit: Amount of time before the quest expires.
Use a number followed by "d" for day(s), "h" for hour(s), "mn" for minute(s), and "s" for second(s).
Specifying with "+" will mark how long until the quest expires.
Specifying without "+" will mark the exact time the quest expires. Format: "d" (optional), [0-23]"h" (required), [0-59]"mn" (optional), [0-59]"s" (optional).
Use a number followed by "d" for day(s), "h" for hour(s), "mn" for minute(s), and "s" for second(s).
Format: "d" (optional), [0-23]"h" (optional), [0-59]"mn" (optional), [0-59]"s" (optional).
Please note the number before "d" only shifts the exact timer to the given day(s).
Example:
- Id: 2069
Title: Tierra Gorge Battle
# The quest expires 5 minutes after being taken.
TimeLimit: +5mn
Specifying without "+" will mark the exact time the quest expires.
Use a number followed by "d" for day(s) to shift the exact timer to the given day(s) or use the days of the week to set the expiration day,
and "h" for hour(s), "mn" for minute(s), and "s" for second(s).
Format: [days of the week] or "d" (optionals), [0-23]"h" (optional), [0-59]"mn" (optional), [0-59]"s" (optional).
Examples:
- Id: 9419
Title: Attack Sky Fortress Invading Prontera
# The quest expires 3 days after being taken at 4am.
TimeLimit: 3d 4h
- Id: 5965
Title: "[Standby] Devil's Special"
# The quest expires Monday at 4am.
TimeLimit: Monday 4h
---------------------------------------

View File

@ -28,7 +28,7 @@
using namespace rathena;
static int split_exact_quest_time(char* modif_p, int* day, int* hour, int* minute, int *second);
static int split_exact_quest_time(char* modif_p, int* week, int* day, int* hour, int* minute, int *second);
const std::string QuestDatabase::getDefaultLocation() {
return std::string(db_path) + "/quest_db.yml";
@ -81,20 +81,25 @@ uint64 QuestDatabase::parseBodyNode(const ryml::NodeRef& node) {
quest->time = static_cast<time_t>(timediff);
}
else {// '+' not found, set to specific time
int32 day, hour, minute, second;
int32 day, hour, minute, second, week;
if (split_exact_quest_time(const_cast<char *>(time.c_str()), &day, &hour, &minute, &second) == 0) {
if (split_exact_quest_time(const_cast<char *>(time.c_str()), &week, &day, &hour, &minute, &second) == 0) {
this->invalidWarning(node["TimeLimit"], "Incorrect TimeLimit format %s given, skipping.\n", time.c_str());
return 0;
}
quest->time = day * 86400 + hour * 3600 + minute * 60 + second;
if (week > 0)
quest->time = hour * 3600 + minute * 60 + second;
else
quest->time = day * 86400 + hour * 3600 + minute * 60 + second;
quest->time_at = true;
quest->time_week = week;
}
} else {
if (!exists) {
quest->time = 0;
quest->time_at = false;
quest->time_week = -1;
}
}
@ -441,8 +446,8 @@ uint64 QuestDatabase::parseBodyNode(const ryml::NodeRef& node) {
}
static int split_exact_quest_time(char* modif_p, int* day, int* hour, int* minute, int *second) {
int d = -1, h = -1, mn = -1, s = -1;
static int split_exact_quest_time(char* modif_p, int* week, int* day, int* hour, int* minute, int *second) {
int w = -1, d = -1, h = -1, mn = -1, s = -1;
nullpo_retr(0, modif_p);
@ -453,7 +458,28 @@ static int split_exact_quest_time(char* modif_p, int* day, int* hour, int* minut
modif_p++;
while (modif_p[0] >= '0' && modif_p[0] <= '9')
modif_p++;
if (modif_p[0] == 's') {
if (strncasecmp(modif_p, "SUNDAY", 6) == 0) {
w = 0;
modif_p = modif_p + 6;
} else if (strncasecmp(modif_p, "MONDAY", 6) == 0) {
w = 1;
modif_p = modif_p + 6;
} else if (strncasecmp(modif_p, "TUESDAY", 7) == 0) {
w = 2;
modif_p = modif_p + 7;
} else if (strncasecmp(modif_p, "WEDNESDAY", 9) == 0) {
w = 3;
modif_p = modif_p + 9;
} else if (strncasecmp(modif_p, "THURSDAY", 8) == 0) {
w = 4;
modif_p = modif_p + 8;
} else if (strncasecmp(modif_p, "FRIDAY", 6) == 0) {
w = 5;
modif_p = modif_p + 6;
} else if (strncasecmp(modif_p, "SATURDAY", 8) == 0) {
w = 6;
modif_p = modif_p + 8;
} else if (modif_p[0] == 's') {
s = value;
modif_p++;
} else if (modif_p[0] == 'm' && modif_p[1] == 'n') {
@ -473,6 +499,7 @@ static int split_exact_quest_time(char* modif_p, int* day, int* hour, int* minut
if (h < 0 || h > 23 || mn > 59 || s > 59) // hour is required
return 0;
*week = w;
*day = max(0,d);
*hour = h;
*minute = max(0,mn);
@ -536,10 +563,18 @@ static time_t quest_time(std::shared_ptr<s_quest_db> qi)
struct tm *lt = localtime(&t);
uint32 time_today = lt->tm_hour * 3600 + lt->tm_min * 60 + lt->tm_sec;
if (time_today < (qi->time % 86400))
return static_cast<time_t>(t + qi->time - time_today);
else // Carry over to the next day
return static_cast<time_t>(t + 86400 + qi->time - time_today);
int32 day_shift = 0;
if (time_today >= (qi->time % 86400)) // Carry over to the next day
day_shift = 1;
if (qi->time_week > -1) {
if (qi->time_week < (lt->tm_wday + day_shift))
day_shift = qi->time_week + 7 - lt->tm_wday;
else
day_shift = qi->time_week - lt->tm_wday;
}
return static_cast<time_t>(t + (day_shift * 86400) + qi->time - time_today);
}
return 0;

View File

@ -42,6 +42,7 @@ struct s_quest_db {
int32 id;
time_t time;
bool time_at;
int32 time_week;
std::vector<std::shared_ptr<s_quest_objective>> objectives;
std::vector<std::shared_ptr<s_quest_dropitem>> dropitem;
std::string name;