Skip to content

Commit

Permalink
Extended TimeLimit format (quest DB) (#8116)
Browse files Browse the repository at this point in the history
  • Loading branch information
Atemo committed Mar 25, 2024
1 parent 42bd87d commit ed2d03d
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 14 deletions.
25 changes: 22 additions & 3 deletions doc/quest_db.txt
Expand Up @@ -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).

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).

Please note the number before "d" only shifts the exact timer to the given day(s).
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

---------------------------------------

Expand Down
57 changes: 46 additions & 11 deletions src/map/quest.cpp
Expand Up @@ -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";
Expand Down Expand Up @@ -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;
}
}

Expand Down Expand Up @@ -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);

Expand All @@ -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') {
Expand All @@ -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);
Expand Down Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions src/map/quest.hpp
Expand Up @@ -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;
Expand Down

0 comments on commit ed2d03d

Please sign in to comment.