Skip to content

Commit

Permalink
Merge pull request #1593 from guilherme-gm/script-setquest
Browse files Browse the repository at this point in the history
Closes #1593 as merged
  • Loading branch information
MishimaHaruna committed Jul 11, 2017
2 parents eef9252 + 79b6949 commit aaa2b23
Show file tree
Hide file tree
Showing 6 changed files with 150 additions and 15 deletions.
28 changes: 27 additions & 1 deletion doc/script_commands.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3408,6 +3408,30 @@ Example :

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

*getcalendartime(<hour>, <minute>{, <day of month>{, <day of week>}})

This function returns the timestamp of the next ocurrence of given time.

Day of Month specifies a day between 1 and 31 in the future, by default its value is -1 (don't use).
Day of Week specifies a day in the week and its valid values are:
0 - SUNDAY
1 - MONDAY
2 - TUESDAY
3 - WEDNESDAY
4 - THURSDAY
5 - FRIDAY
6 - SATURDAY

In order to use Day of Week, you must use Day of Month as -1.
If for some reason the command fails, it'll return -1.

Examples :
getcalendartime(19, 00); // Next 7 pm
getcalendartime(19, 00, 6); // Next day 6 of the month, at 7pm
getcalendartime(19, 10, -1, 1); // Next Monday, at 7:10pm

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

*gettimestr(<format string>, <max length>)

This function will return a string containing time data as specified by
Expand Down Expand Up @@ -9152,9 +9176,11 @@ Example

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

*setquest(<ID>)
*setquest(<ID>{, <Time Limit>})

Place quest of <ID> in the users quest log, the state of which is "active".
If Time Limit is given, this quest will have its expire time set to <Time Limit>, an UNIX epoch time,
ignoring quest_db setting.

If questinfo() is set, and the same ID is specified here, the icon will be cleared when the quest is set.

Expand Down
7 changes: 7 additions & 0 deletions src/map/date.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,13 @@ int date_get_sec(void)
return lt->tm_sec;
}

int date_get_dayofweek(void)
{
time_t t = time(NULL);
struct tm *lt = localtime(&t);
return lt->tm_wday;
}

/*==========================================
* Star gladiator related checks
*------------------------------------------*/
Expand Down
1 change: 1 addition & 0 deletions src/map/date.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ int date_get_day(void);
int date_get_hour(void);
int date_get_min(void);
int date_get_sec(void);
int date_get_dayofweek(void);

bool is_day_of_sun(void);
bool is_day_of_moon(void);
Expand Down
21 changes: 12 additions & 9 deletions src/map/quest.c
Original file line number Diff line number Diff line change
Expand Up @@ -103,22 +103,23 @@ int quest_pc_login(struct map_session_data *sd)
*
* New quest will be added as Q_ACTIVE.
*
* @param sd Player's data
* @param quest_id ID of the quest to add.
* @param sd Player's data
* @param quest_id ID of the quest to add.
* @param time_limit Custom time, in UNIX epoch, for this quest
* @return 0 in case of success, nonzero otherwise
*/
int quest_add(struct map_session_data *sd, int quest_id)
int quest_add(struct map_session_data *sd, int quest_id, unsigned int time_limit)
{
int n;
struct quest_db *qi = quest->db(quest_id);

nullpo_retr(-1, sd);
if( qi == &quest->dummy ) {
if (qi == &quest->dummy) {
ShowError("quest_add: quest %d not found in DB.\n", quest_id);
return -1;
}

if( quest->check(sd, quest_id, HAVEQUEST) >= 0 ) {
if (quest->check(sd, quest_id, HAVEQUEST) >= 0) {
ShowError("quest_add: Character %d already has quest %d.\n", sd->status.char_id, quest_id);
return -1;
}
Expand All @@ -130,15 +131,17 @@ int quest_add(struct map_session_data *sd, int quest_id)
sd->avail_quests++;
RECREATE(sd->quest_log, struct quest, sd->num_quests);

if( sd->avail_quests != sd->num_quests ) {
if (sd->avail_quests != sd->num_quests) {
// The character has some completed quests, make room before them so that they will stay at the end of the array
memmove(&sd->quest_log[n+1], &sd->quest_log[n], sizeof(struct quest)*(sd->num_quests-sd->avail_quests));
}

memset(&sd->quest_log[n], 0, sizeof(struct quest));

sd->quest_log[n].quest_id = qi->id;
if( qi->time )
if (time_limit != 0)
sd->quest_log[n].time = time_limit;
else if (qi->time != 0)
sd->quest_log[n].time = (unsigned int)(time(NULL) + qi->time);
sd->quest_log[n].state = Q_ACTIVE;

Expand All @@ -147,8 +150,8 @@ int quest_add(struct map_session_data *sd, int quest_id)
clif->quest_add(sd, &sd->quest_log[n]);
clif->quest_update_objective(sd, &sd->quest_log[n]);

if( map->save_settings&64 )
chrif->save(sd,0);
if ((map->save_settings & 64) != 0)
chrif->save(sd, 0);

return 0;
}
Expand Down
2 changes: 1 addition & 1 deletion src/map/quest.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ struct quest_interface {
/* */
struct quest_db *(*db) (int quest_id);
int (*pc_login) (struct map_session_data *sd);
int (*add) (struct map_session_data *sd, int quest_id);
int (*add) (struct map_session_data *sd, int quest_id, unsigned int time_limit);
int (*change) (struct map_session_data *sd, int qid1, int qid2);
int (*delete) (struct map_session_data *sd, int quest_id);
int (*update_objective_sub) (struct block_list *bl, va_list ap);
Expand Down
106 changes: 102 additions & 4 deletions src/map/script.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include "map/chat.h"
#include "map/chrif.h"
#include "map/clif.h"
#include "map/date.h"
#include "map/elemental.h"
#include "map/guild.h"
#include "map/homunculus.h"
Expand Down Expand Up @@ -20336,19 +20337,21 @@ BUILDIN(setquest)
{
unsigned short i;
int quest_id;
unsigned int time_limit;
struct map_session_data *sd = script->rid2sd(st);

if (sd == NULL)
return true;

quest_id = script_getnum(st, 2);
time_limit = script_hasdata(st, 3) ? script_getnum(st, 3) : 0;

quest->add(sd, quest_id);
quest->add(sd, quest_id, time_limit);

// If questinfo is set, remove quest bubble once quest is set.
for(i = 0; i < map->list[sd->bl.m].qi_count; i++) {
for (i = 0; i < map->list[sd->bl.m].qi_count; i++) {
struct questinfo *qi = &map->list[sd->bl.m].qi_data[i];
if( qi->quest_id == quest_id ) {
if (qi->quest_id == quest_id) {
#if PACKETVER >= 20120410
clif->quest_show_event(sd, &qi->nd->bl, 9999, 0);
#else
Expand Down Expand Up @@ -23209,6 +23212,100 @@ BUILDIN(mergeitem)
return true;
}

// getcalendartime(<day of month>, <day of week>{, <hour>{, <minute>}});
// Returns the UNIX Timestamp of next ocurrency of given time
BUILDIN(getcalendartime)
{
struct tm info = { 0 };
int day_of_month = script_hasdata(st, 4) ? script_getnum(st, 4) : -1;
int day_of_week = script_hasdata(st, 5) ? script_getnum(st, 5) : -1;
int year = date_get_year();
int month = date_get_month();
int day = date_get_day();
int cur_hour = date_get_hour();
int cur_min = date_get_min();
int hour = script_getnum(st, 2);
int minute = script_getnum(st, 3);

info.tm_sec = 0;
info.tm_min = minute;
info.tm_hour = hour;
info.tm_mday = day;
info.tm_mon = month - 1;
info.tm_year = year - 1900;

if (day_of_month > -1 && day_of_week > -1) {
ShowError("script:getcalendartime: You must only specify a day_of_week or a day_of_month, not both\n");
script_pushint(st, -1);
return false;
}
if (day_of_month > -1 && (day_of_month < 1 || day_of_month > 31)) {
ShowError("script:getcalendartime: Day of Month in invalid range. Must be between 1 and 31.\n");
script_pushint(st, -1);
return false;
}
if (day_of_week > -1 && (day_of_week < 0 || day_of_week > 6)) {
ShowError("script:getcalendartime: Day of Week in invalid range. Must be between 0 and 6.\n");
script_pushint(st, -1);
return false;
}
if (hour > -1 && (hour > 23)) {
ShowError("script:getcalendartime: Hour in invalid range. Must be between 0 and 23.\n");
script_pushint(st, -1);
return false;
}
if (minute > -1 && (minute > 59)) {
ShowError("script:getcalendartime: Minute in invalid range. Must be between 0 and 59.\n");
script_pushint(st, -1);
return false;
}
if (hour == -1 || minute == -1) {
ShowError("script:getcalendartime: Minutes and Hours are required\n");
script_pushint(st, -1);
return false;
}

if (day_of_month > -1) {
if (day_of_month < day) { // Next Month
info.tm_mon++;
} else if (day_of_month == day) { // Today
if (hour < cur_hour || (hour == cur_hour && minute < cur_min)) { // But past time, next month
info.tm_mon++;
}
}

// Loops until month has finding a month that has day_of_month
do {
time_t t;
struct tm *lt;
info.tm_mday = day_of_month;
t = mktime(&info);
lt = localtime(&t);
info = *lt;
} while (info.tm_mday != day_of_month);
} else if (day_of_week > -1) {
int cur_wday = date_get_dayofweek();

if (day_of_week > cur_wday) { // This week
info.tm_mday += (day_of_week - cur_wday);
} else if (day_of_week == cur_wday) { // Today
if (hour < cur_hour || (hour == cur_hour && minute <= cur_min)) {
info.tm_mday += 7; // Next week
}
} else if (day_of_week < cur_wday) { // Next week
info.tm_mday += (7 - cur_wday + day_of_week);
}
} else if (day_of_week == -1 && day_of_month == -1) { // Next occurence of hour/min
if (hour < cur_hour || (hour == cur_hour && minute < cur_min)) {
info.tm_mday++;
}
}

script_pushint(st, mktime(&info));

return true;
}

/** place holder for the translation macro **/
BUILDIN(_)
{
Expand Down Expand Up @@ -23918,7 +24015,7 @@ void script_parse_builtin(void) {

//Quest Log System [Inkfish]
BUILDIN_DEF(questinfo, "ii??"),
BUILDIN_DEF(setquest, "i"),
BUILDIN_DEF(setquest, "i?"),
BUILDIN_DEF(erasequest, "i?"),
BUILDIN_DEF(completequest, "i?"),
BUILDIN_DEF(questprogress, "i?"),
Expand Down Expand Up @@ -23970,6 +24067,7 @@ void script_parse_builtin(void) {
BUILDIN_DEF(removechannelhandler, "ss"),
BUILDIN_DEF(showscript, "s?"),
BUILDIN_DEF(mergeitem,""),
BUILDIN_DEF(getcalendartime, "ii??"),
BUILDIN_DEF(_,"s"),
BUILDIN_DEF2(_, "_$", "s"),
};
Expand Down

0 comments on commit aaa2b23

Please sign in to comment.