conf/battle/feature.conf | 3 +
src/map/atcommand.c | 166 +++++++++++++++++++++++++++++++++++++++++++++++
src/map/battle.c | 2 +
src/map/battle.h | 2 +
src/map/chrif.c | 110 +++++++++++++++++++++++++++++++
src/map/chrif.h | 9 +++
src/map/clif.c | 13 ++++
src/map/pc.c | 5 ++
src/map/script.c | 154 +++++++++++++++++++++++++++++++++++++++++++
9 files changed, 464 insertions(+)
diff --git a/conf/battle/feature.conf b/conf/battle/feature.conf
index 161ea32..05c759c 100644
--- a/conf/battle/feature.conf
+++ b/conf/battle/feature.conf
@@ -27,3 +27,6 @@ feature.banking: on
// Feature became unstable on clients 2012 onwards (exact date not known),
// it has been fixed on clients 2013-05-15 onwards however.
feature.auction: off
+
+// change the announcement color for maintenance
+maintenance_color: 0xFFFF00
diff --git a/src/map/atcommand.c b/src/map/atcommand.c
index 497e465..c17bfe1 100644
--- a/src/map/atcommand.c
+++ b/src/map/atcommand.c
@@ -9372,6 +9372,170 @@ static inline void atcmd_channel_help(int fd, const char *command, bool can_crea
clif->message(fd,atcmd_output);
return true;
}
+
+ACMD(maintenance) {
+ int group_id = 0, kick_duration = 0, maintenance_duration = 0;
+ char reason[99], esc_reason[198], esc_name[46], min_display[3];
+ short weekday = 0, hour = 0, minute = 0;
+ if ( chrif->maintenance_starttime > (int)time(NULL) ) {
+ int countdown = chrif->maintenance_starttime - (int)time(NULL);
+ clif->message( fd, "Type '@maintenanceoff' to turn off maintenance mode." );
+ safesnprintf( atcmd_output, 255, "Maintenance mode will start in %d min %d sec.", countdown /60, countdown %60 );
+ clif->message( fd, atcmd_output );
+ return true;
+ }
+ if ( chrif->maintenance_endtime > (int)time(NULL) ) {
+ int countdown = chrif->maintenance_endtime - (int)time(NULL);
+ clif->message( fd, "Type '@maintenanceoff' to turn off maintenance mode." );
+ safesnprintf( atcmd_output, 255, "Server is currently in maintenance mode, will end in %d min %d sec on %s", countdown /60, countdown %60, chrif->maintenance_timeformat );
+ clif->message( fd, atcmd_output );
+ return true;
+ }
+ if ( !message || !*message ) {
+ clif->message( fd, "@maintenance Syntax :" );
+ clif->message( fd, "@maintenance <Group ID can stay 1~99> <duration to kick in minute> <maintenance duration in minute> <reason>" );
+ return false;
+ }
+ {
+ int i = 0, j = 0, k = 0, l = strlen( message );
+ char *temp = (char*)aMalloc( strlen( message ) +1 );
+ while ( i <= l && k < 3 ) {
+ if ( message[i] != ' ' && message[i] != '\0' ) {
+ temp[j++] = message[i];
+ }
+ else if ( message[i-1] != ' ' ) {
+ temp[j] = '\0';
+ if ( k == 0 )
+ group_id = atoi( temp );
+ else if ( k == 1 )
+ kick_duration = atoi( temp );
+ else if ( k == 2 )
+ maintenance_duration = atoi( temp );
+ k++;
+ j = 0;
+ }
+ i++;
+ }
+ safestrncpy( reason, &message[i], 99 );
+ aFree( temp );
+ if ( k < 3 ) {
+ clif->message( sd->fd, "@maintenance Syntax :" );
+ clif->message( sd->fd, "@maintenance <Group ID can stay 1~99> <duration to kick in minute> <maintenance duration in minute> <reason>" );
+ return false;
+ }
+ }
+ if ( !group_id ) {
+ clif->message( fd, "The Group ID field cannot be 0, otherwise normal player able to login." );
+ return false;
+ }
+ if ( group_id < 1 || group_id > 99 ) {
+ safesnprintf( atcmd_output, 99, "Invalid Group ID %d. Range must between 1~99.", group_id );
+ clif->message( fd, atcmd_output );
+ return false;
+ }
+ if ( kick_duration <= 0 ) {
+ clif->message( fd, "Kick duration cannot be 0 or negative numbers." );
+ return false;
+ }
+ if ( kick_duration > 1440 ) {
+ clif->message( fd, "Kick duration cannot be more than 1 day." );
+ return false;
+ }
+ if ( maintenance_duration <= 0 ) {
+ clif->message( fd, "Maintenance duration cannot be 0 or negative numbers." );
+ return false;
+ }
+ if ( maintenance_duration > 10080 ) {
+ clif->message( fd, "Maintenance duration cannot be more than 1 week." );
+ return false;
+ }
+ if ( strlen(reason) < 4 ) {
+ clif->message( fd, "You must input a valid reason for doing this." );
+ return false;
+ }
+ SQL->EscapeString( map->mysql_handle, esc_name, sd->status.name );
+ SQL->EscapeString( map->mysql_handle, esc_reason, reason );
+ if ( SQL->Query( map->mysql_handle, "insert into maintenance values ( null, %d, '%s', '%s', %d, now(), timestampadd( minute, %d, now() ), timestampadd( minute, %d, now() ) )", sd->status.account_id, esc_name, esc_reason, group_id, kick_duration, kick_duration + maintenance_duration ) == SQL_ERROR ) {
+ Sql_ShowDebug( map->mysql_handle );
+ return false;
+ }
+ if ( SQL->Query( map->mysql_handle, "select unix_timestamp( start_time ), unix_timestamp( end_time ), weekday( end_time ), hour( end_time ), minute( end_time ) from maintenance where id = ( select max(id) from maintenance )" ) == SQL_ERROR ) {
+ Sql_ShowDebug( map->mysql_handle );
+ return false;
+ }
+ else if ( SQL->NextRow( map->mysql_handle ) == SQL_SUCCESS ) {
+ char *data;
+ chrif->maintenance_group = group_id;
+ if ( SQL->GetData( map->mysql_handle, 0, &data, NULL ) == SQL_SUCCESS )
+ chrif->maintenance_starttime = atoi(data);
+ if ( SQL->GetData( map->mysql_handle, 1, &data, NULL ) == SQL_SUCCESS )
+ chrif->maintenance_endtime = atoi(data);
+ if ( SQL->GetData( map->mysql_handle, 2, &data, NULL ) == SQL_SUCCESS )
+ weekday = atoi(data);
+ if ( SQL->GetData( map->mysql_handle, 3, &data, NULL ) == SQL_SUCCESS )
+ hour = atoi(data);
+ if ( SQL->GetData( map->mysql_handle, 4, &data, NULL ) == SQL_SUCCESS )
+ minute = atoi(data);
+ SQL->FreeResult( map->mysql_handle );
+ }
+ else {
+ SQL->FreeResult( map->mysql_handle );
+ return false;
+ }
+ { // stupid date_format doesn't work
+ char* weekdayname[7] = { "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" };
+ char am_pm[3];
+ if ( hour == 0 ) {
+ hour = 12;
+ safesnprintf( am_pm, 3, "AM" );
+ }
+ else if ( hour < 12 )
+ safesnprintf( am_pm, 3, "AM" );
+ else {
+ hour = hour - 12;
+ safesnprintf( am_pm, 3, "PM" );
+ }
+ if ( minute < 10 )
+ safesnprintf( min_display, 3, "0%d", minute );
+ else
+ safesnprintf( min_display, 3, "%d", minute );
+ safesnprintf( chrif->maintenance_timeformat, 24, "%s, %d:%s %s", weekdayname[ weekday ], hour, min_display, am_pm );
+ safesnprintf( atcmd_output, 255, "Maintenance mode will be commence in %d minutes. Players are adviced to log out right now. Maintenance last %d minutes. Server will come back up on %s", kick_duration, maintenance_duration, chrif->maintenance_timeformat );
+ intif->broadcast2( atcmd_output, strlen(atcmd_output) +1, battle_config.maintenance_color, 0x190, 12, 0, 0);
+ }
+ chrif->maintenance_countid = timer->add( timer->gettick() +( ( kick_duration == 1 )? 1000 : 60000 ), chrif->maintenance_countdown, 0, 0 );
+ ShowStatus( CL_YELLOW "Maintenance will start in %d min by " CL_GREEN "%s" CL_RESET ".\n", kick_duration, sd->status.name );
+ return true;
+}
+
+ACMD(maintenanceoff) {
+ char esc_name[46];
+ if ( chrif->maintenance_endtime <= (int)time(NULL) ) {
+ clif->message( fd, "The server is currently in not in maintenance mode." );
+ return true;
+ }
+ SQL->EscapeString( map->mysql_handle, esc_name, sd->status.name );
+ if ( SQL->Query( map->mysql_handle, "insert into maintenance values ( null, %d, '%s', ' @maintenanceoff', 0, null, now(), now() )", sd->status.account_id, esc_name ) == SQL_ERROR ) {
+ Sql_ShowDebug( map->mysql_handle );
+ return false;
+ }
+ chrif->maintenance_group = 0;
+ chrif->maintenance_starttime = (int)time(NULL);
+ chrif->maintenance_endtime = (int)time(NULL);
+ if ( chrif->maintenance_countid != INVALID_TIMER ) {
+ timer->delete( chrif->maintenance_countid, chrif->maintenance_countdown );
+ chrif->maintenance_countid = INVALID_TIMER;
+ }
+ if ( chrif->maintenance_timerid != INVALID_TIMER ) {
+ timer->delete( chrif->maintenance_timerid, chrif->maintenance_progress );
+ chrif->maintenance_timerid = INVALID_TIMER;
+ }
+ safesnprintf( atcmd_output, CHAT_SIZE_MAX, "%s ended the Maintenance mode. Players are able to login now.", sd->status.name );
+ intif->broadcast2( atcmd_output, strlen(atcmd_output) +1, battle_config.maintenance_color, 0x190, 12, 0, 0);
+ ShowStatus( CL_YELLOW "Maintenance has ended by " CL_GREEN "%s" CL_RESET ".\n", sd->status.name );
+ return true;
+}
+
/**
* Fills the reference of available commands in atcommand DBMap
**/
@@ -9382,6 +9546,8 @@ void atcommand_basecommands(void) {
* Command reference list, place the base of your commands here
**/
AtCommandInfo atcommand_base[] = {
+ ACMD_DEF(maintenance),
+ ACMD_DEF(maintenanceoff),
ACMD_DEF2("warp", mapmove),
ACMD_DEF(where),
ACMD_DEF(jumpto),
diff --git a/src/map/battle.c b/src/map/battle.c
index c511c58..ba23085 100644
--- a/src/map/battle.c
+++ b/src/map/battle.c
@@ -6826,6 +6826,8 @@ bool battle_check_range(struct block_list *src, struct block_list *bl, int range
{ "guild_castle_expulsion", &battle_config.guild_castle_expulsion, 0, 0, 1, },
{ "song_timer_reset", &battle_config.song_timer_reset, 0, 0, 1, },
{ "snap_dodge", &battle_config.snap_dodge, 0, 0, 1, },
+
+ { "maintenance_color", &battle_config.maintenance_color, 0xFFFF00, 0, INT_MAX, },
};
#ifndef STATS_OPT_OUT
/**
diff --git a/src/map/battle.h b/src/map/battle.h
index 734a618..66136ca 100644
--- a/src/map/battle.h
+++ b/src/map/battle.h
@@ -477,6 +477,8 @@ struct Battle_Config {
int song_timer_reset; // [csnv]
int snap_dodge; // Enable or disable dodging damage snapping away [csnv]
+
+ int maintenance_color;
};
extern struct Battle_Config battle_config;
diff --git a/src/map/chrif.c b/src/map/chrif.c
index 34e92be..4af6677 100644
--- a/src/map/chrif.c
+++ b/src/map/chrif.c
@@ -413,6 +413,63 @@ bool chrif_changemapserverack(int account_id, int login_id1, int login_id2, int
return (!login_id1)?false:true; // Is this the best approach here?
}
+int chrif_maintenance_countdown( int tid, int64 tick, int id, intptr data ) {
+ char output[CHAT_SIZE_MAX];
+ int countdown = chrif->maintenance_starttime - (int)time(NULL);
+ if ( countdown > 90 ) {
+ safesnprintf( output, CHAT_SIZE_MAX, "Maintainance will start in %d minutes", countdown /60 );
+ intif->broadcast2( output, strlen(output) +1, battle_config.maintenance_color, 0x190, 12, 0, 0);
+ timer->delete( chrif->maintenance_countid, chrif->maintenance_countdown );
+ if ( ( countdown % 60 ) > 0 ) // fine tune the timer
+ chrif->maintenance_countid = timer->add( timer->gettick() + ( ( countdown % 60 ) * 1000 ), chrif->maintenance_countdown, 0, 0 );
+ else
+ chrif->maintenance_countid = timer->add( timer->gettick() + 60000, chrif->maintenance_countdown, 0, 0 );
+ }
+ else if ( countdown > 15 ) {
+ safesnprintf( output, CHAT_SIZE_MAX, "Maintainance will start in %d seconds", countdown );
+ intif->broadcast2( output, strlen(output) +1, battle_config.maintenance_color, 0x190, 12, 0, 0);
+ timer->delete( chrif->maintenance_countid, chrif->maintenance_countdown );
+ if ( ( countdown % 10 ) > 0 ) // fine tune the timer
+ chrif->maintenance_countid = timer->add( timer->gettick() + ( ( countdown % 10 ) * 1000 ), chrif->maintenance_countdown, 0, 0 );
+ else
+ chrif->maintenance_countid = timer->add( timer->gettick() + 10000, chrif->maintenance_countdown, 0, 0 );
+ }
+ else if ( countdown > 0 ) {
+ safesnprintf( output, CHAT_SIZE_MAX, "Maintainance will start in %d seconds", countdown );
+ intif->broadcast2( output, strlen(output) +1, battle_config.maintenance_color, 0x190, 12, 0, 0);
+ timer->delete( chrif->maintenance_countid, chrif->maintenance_countdown );
+ chrif->maintenance_countid = timer->add( timer->gettick() + 1000, chrif->maintenance_countdown, 0, 0 );
+ }
+ else {
+ struct s_mapiterator* iter = mapit_getallusers();
+ TBL_PC *sd;
+ safesnprintf( output, CHAT_SIZE_MAX, "Maintainance starts now. Every player will be kick out." );
+ intif->broadcast2( output, strlen(output) +1, battle_config.maintenance_color, 0x190, 12, 0, 0);
+ for ( sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); sd = (TBL_PC*)mapit->next(iter) )
+ if ( sd->group_id < chrif->maintenance_group )
+ clif->authfail_fd( sd->fd, 1 );
+ mapit->free(iter);
+ timer->delete( chrif->maintenance_countid, chrif->maintenance_countdown );
+ chrif->maintenance_countid = INVALID_TIMER;
+ chrif->maintenance_timerid = timer->add( timer->gettick() + ( ( chrif->maintenance_endtime - chrif->maintenance_starttime )*1000 ), chrif->maintenance_progress, 0, 0 );
+ ShowStatus( CL_YELLOW "Maintenance has started." CL_RESET "\n" );
+ }
+ return false;
+}
+
+int chrif_maintenance_progress( int tid, int64 tick, int id, intptr data ) {
+ char output[CHAT_SIZE_MAX];
+ timer->delete( chrif->maintenance_timerid, chrif->maintenance_progress );
+ chrif->maintenance_timerid = INVALID_TIMER;
+ safesnprintf( output, CHAT_SIZE_MAX, "Maintenance mode has ended. Players are able to login now." );
+ intif->broadcast2( output, strlen(output) +1, battle_config.maintenance_color, 0x190, 12, 0, 0);
+ chrif->maintenance_group = 0;
+ chrif->maintenance_starttime = (int)time(NULL);
+ chrif->maintenance_endtime = (int)time(NULL);
+ ShowStatus( CL_YELLOW "Maintenance has ended." CL_RESET "\n" );
+ return false;
+}
+
/*==========================================
*
*------------------------------------------*/
@@ -439,6 +496,56 @@ void chrif_connectack(int fd) {
sockt->datasync(fd, true);
chrif->skillid2idx(fd);
+
+ chrif->maintenance_countid = INVALID_TIMER;
+ chrif->maintenance_timerid = INVALID_TIMER;
+
+ if ( SQL->Query( map->mysql_handle, "select minlv2connect, unix_timestamp( start_time ), unix_timestamp( end_time ), weekday( end_time ), hour( end_time ), minute( end_time ) from maintenance where id = ( select max(id) from maintenance )" ) == SQL_ERROR )
+ Sql_ShowDebug( map->mysql_handle );
+ else if ( SQL->NextRow( map->mysql_handle ) == SQL_SUCCESS ) {
+ short weekday = 0, hour = 0, minute = 0;
+ char *data, *weekdayname[7] = { "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" }, am_pm[3], min_display[3];
+ if ( SQL->GetData( map->mysql_handle, 0, &data, NULL ) == SQL_SUCCESS )
+ chrif->maintenance_group = atoi(data);
+ if ( SQL->GetData( map->mysql_handle, 1, &data, NULL ) == SQL_SUCCESS )
+ chrif->maintenance_starttime = atoi(data);
+ if ( SQL->GetData( map->mysql_handle, 2, &data, NULL ) == SQL_SUCCESS )
+ chrif->maintenance_endtime = atoi(data);
+ if ( SQL->GetData( map->mysql_handle, 3, &data, NULL ) == SQL_SUCCESS )
+ weekday = atoi(data);
+ if ( SQL->GetData( map->mysql_handle, 4, &data, NULL ) == SQL_SUCCESS )
+ hour = atoi(data);
+ if ( SQL->GetData( map->mysql_handle, 5, &data, NULL ) == SQL_SUCCESS )
+ minute = atoi(data);
+ if ( hour == 0 ) {
+ hour = 12;
+ safesnprintf( am_pm, 3, "AM" );
+ }
+ else if ( hour < 12 )
+ safesnprintf( am_pm, 3, "AM" );
+ else {
+ hour = hour - 12;
+ safesnprintf( am_pm, 3, "PM" );
+ }
+ if ( minute < 10 )
+ safesnprintf( min_display, 3, "0%d", minute );
+ else
+ safesnprintf( min_display, 3, "%d", minute );
+ safesnprintf( chrif->maintenance_timeformat, 24, "%s, %d:%s %s", weekdayname[ weekday ], hour, min_display, am_pm );
+ }
+ if ( chrif->maintenance_starttime > (int)time(NULL) ) {
+ int countdown = chrif->maintenance_starttime - (int)time(NULL);
+ if ( countdown > 60 )
+ chrif->maintenance_countid = timer->add( timer->gettick() + ( ( countdown % 60 )*1000 ), chrif->maintenance_countdown, 0, 0 );
+ else
+ chrif->maintenance_countid = timer->add( timer->gettick() + 1000, chrif->maintenance_countdown, 0, 0 );
+ ShowStatus( CL_YELLOW "Maintenance will start in %d min %d sec." CL_RESET "\n", countdown /60, countdown %60 );
+ }
+ else if ( chrif->maintenance_endtime > (int)time(NULL) ) {
+ int countdown = chrif->maintenance_endtime - (int)time(NULL);
+ chrif->maintenance_timerid = timer->add( timer->gettick() + ( countdown *1000 ), chrif->maintenance_progress, 0, 0 );
+ ShowStatus( CL_YELLOW "Maintenance will end in %d min %d sec on %s." CL_RESET "\n", countdown/60, countdown %60, chrif->maintenance_timeformat );
+ }
}
/**
@@ -1754,4 +1861,7 @@ void chrif_defaults(void) {
chrif->parse = chrif_parse;
chrif->save_scdata_single = chrif_save_scdata_single;
chrif->del_scdata_single = chrif_del_scdata_single;
+
+ chrif->maintenance_countdown = chrif_maintenance_countdown;
+ chrif->maintenance_progress = chrif_maintenance_progress;
}
diff --git a/src/map/chrif.h b/src/map/chrif.h
index 11baaf5..278d88d 100644
--- a/src/map/chrif.h
+++ b/src/map/chrif.h
@@ -146,6 +146,15 @@ struct chrif_interface {
int (*parse) (int fd);
void (*save_scdata_single) (int account_id, int char_id, short type, struct status_change_entry *sce);
void (*del_scdata_single) (int account_id, int char_id, short type);
+ int (*maintenance_countdown) ( int tid, int64 tick, int id, intptr data );
+ int (*maintenance_progress) ( int tid, int64 tick, int id, intptr data );
+
+ int maintenance_group;
+ int maintenance_starttime;
+ int maintenance_endtime;
+ int maintenance_countid;
+ int maintenance_timerid;
+ char maintenance_timeformat[24];
};
struct chrif_interface *chrif;
diff --git a/src/map/clif.c b/src/map/clif.c
index f6ab3f4..921bdbb 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -9274,6 +9274,19 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) {
#endif
bool first_time = false;
+ if ( sd->state.connect_new ) {
+ if ( chrif->maintenance_starttime > time(NULL) ) {
+ char output[CHAT_SIZE_MAX];
+ safesnprintf( output, CHAT_SIZE_MAX, "Maintenance starts in %d min %d sec, last %d minutes. Server up by %s", ( chrif->maintenance_starttime - (int)time(NULL) ) /60, ( chrif->maintenance_starttime - (int)time(NULL) ) %60, ( chrif->maintenance_endtime - chrif->maintenance_starttime ) /60, chrif->maintenance_timeformat );
+ clif->message( sd->fd, output );
+ }
+ else if ( chrif->maintenance_endtime > time(NULL) ) {
+ char output[CHAT_SIZE_MAX];
+ safesnprintf( output, CHAT_SIZE_MAX, "Server is currently in maintenance mode, will end in %d min %d sec on %s", ( chrif->maintenance_endtime - (int)time(NULL) ) /60, ( chrif->maintenance_endtime - (int)time(NULL) ) %60, chrif->maintenance_timeformat );
+ clif->message( sd->fd, output );
+ }
+ }
+
if(sd->bl.prev != NULL)
return;
diff --git a/src/map/pc.c b/src/map/pc.c
index e28d054..e96b1ae 100644
--- a/src/map/pc.c
+++ b/src/map/pc.c
@@ -970,6 +970,11 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim
int64 tick = timer->gettick();
uint32 ip = session[sd->fd]->client_addr;
+ if ( (int)time(NULL) > chrif->maintenance_starttime && chrif->maintenance_endtime > (int)time(NULL) && group_id < chrif->maintenance_group ) {
+ clif->authfail_fd( sd->fd, 1 );
+ return false;
+ }
+
sd->login_id2 = login_id2;
if (pc->set_group(sd, group_id) != 0) {
diff --git a/src/map/script.c b/src/map/script.c
index f776b1b..90824b3 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -18773,10 +18773,164 @@ bool script_hp_add(char *name, char *args, bool (*func)(struct script_state *st)
return script->add_builtin(&buildin, true);
}
+// maintenance <Group ID can stay 1~99>, <duration to kick in minute>, <maintenance duration in minute> { , <reason> };
+BUILDIN(maintenance) {
+ int group_id = 0, kick_duration = 0, maintenance_duration = 0;
+ char reason[99], esc_reason[198], min_display[3];
+ short weekday = 0, hour = 0, minute = 0;
+ if ( chrif->maintenance_endtime > time(NULL) ) {
+ ShowError( "buildin_maintenance: Maintenance is currently ON.\n" );
+ return false;
+ }
+ group_id = script_getnum(st,2);
+ kick_duration = script_getnum(st,3);
+ maintenance_duration = script_getnum(st,4);
+ if ( !group_id ) {
+ ShowError( "buildin_maintenance: Group ID field cannot be 0.\n" );
+ return false;
+ }
+ if ( group_id < 1 || group_id > 99 ) {
+ ShowError( "buildin_maintenance: Invalid Group ID %d. Range must between 1~99.\n", group_id );
+ return false;
+ }
+ if ( kick_duration <= 0 ) {
+ ShowError( "buildin_maintenance: Kick duration cannot be 0 or negative numbers.\n" );
+ return false;
+ }
+ if ( kick_duration > 1440 ) {
+ ShowError( "buildin_maintenance: Kick duration cannot be more than 1 day.\n" );
+ return false;
+ }
+ if ( maintenance_duration <= 0 ) {
+ ShowError( "buildin_maintenance: Maintenance duration cannot be 0 or negative numbers.\n" );
+ return false;
+ }
+ if ( maintenance_duration > 10080 ) {
+ ShowError( "buildin_maintenance: Maintenance duration cannot be more than 1 week.\n" );
+ return false;
+ }
+ safesnprintf( reason, 99, script_hasdata(st,5)? script_getstr(st,5) : " *Regular server maintenance*" );
+ SQL->EscapeString( map->mysql_handle, esc_reason, reason );
+ if ( SQL->Query( map->mysql_handle, "insert into maintenance values ( null, 0, 'NPC', '%s', %d, now(), timestampadd( minute, %d, now() ), timestampadd( minute, %d, now() ) )", esc_reason, group_id, kick_duration, kick_duration + maintenance_duration ) == SQL_ERROR ) {
+ Sql_ShowDebug( map->mysql_handle );
+ return false;
+ }
+ if ( SQL->Query( map->mysql_handle, "select unix_timestamp( start_time ), unix_timestamp( end_time ), weekday( end_time ), hour( end_time ), minute( end_time ) from maintenance where id = ( select max(id) from maintenance )" ) == SQL_ERROR ) {
+ Sql_ShowDebug( map->mysql_handle );
+ return false;
+ }
+ else if ( SQL->NextRow( map->mysql_handle ) == SQL_SUCCESS ) {
+ char *data;
+ chrif->maintenance_group = group_id;
+ if ( SQL->GetData( map->mysql_handle, 0, &data, NULL ) == SQL_SUCCESS )
+ chrif->maintenance_starttime = atoi(data);
+ if ( SQL->GetData( map->mysql_handle, 1, &data, NULL ) == SQL_SUCCESS )
+ chrif->maintenance_endtime = atoi(data);
+ if ( SQL->GetData( map->mysql_handle, 2, &data, NULL ) == SQL_SUCCESS )
+ weekday = atoi(data);
+ if ( SQL->GetData( map->mysql_handle, 3, &data, NULL ) == SQL_SUCCESS )
+ hour = atoi(data);
+ if ( SQL->GetData( map->mysql_handle, 4, &data, NULL ) == SQL_SUCCESS )
+ minute = atoi(data);
+ SQL->FreeResult( map->mysql_handle );
+ }
+ else {
+ SQL->FreeResult( map->mysql_handle );
+ return false;
+ }
+ { // stupid date_format doesn't work
+ char* weekdayname[7] = { "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" };
+ char am_pm[3], output[CHAT_SIZE_MAX];
+ if ( hour == 0 ) {
+ hour = 12;
+ safesnprintf( am_pm, 3, "AM" );
+ }
+ else if ( hour < 12 )
+ safesnprintf( am_pm, 3, "AM" );
+ else {
+ hour = hour - 12;
+ safesnprintf( am_pm, 3, "PM" );
+ }
+ if ( minute < 10 )
+ safesnprintf( min_display, 3, "0%d", minute );
+ else
+ safesnprintf( min_display, 3, "%d", minute );
+ safesnprintf( chrif->maintenance_timeformat, 24, "%s, %d:%s %s", weekdayname[ weekday ], hour, min_display, am_pm );
+ safesnprintf( output, CHAT_SIZE_MAX, "Maintenance mode will be commence in %d minutes. Players are adviced to log out right now. Maintenance last %d minutes. Server will come back up on %s", kick_duration, maintenance_duration, chrif->maintenance_timeformat );
+ intif->broadcast2( output, strlen(output) +1, battle_config.maintenance_color, 0x190, 12, 0, 0);
+ }
+ chrif->maintenance_countid = timer->add( timer->gettick() +( ( kick_duration == 1 )? 1000 : 60000 ), chrif->maintenance_countdown, 0, 0 );
+ ShowStatus( CL_YELLOW "Maintenance will start in %d min" CL_RESET ".\n", kick_duration );
+ return true;
+}
+
+BUILDIN(maintenanceoff) {
+ char reason[99], esc_reason[198];
+ if ( chrif->maintenance_endtime <= time(NULL) ) {
+ ShowError( "buildin_maintenanceoff: Maintenance is currently OFF.\n" );
+ return false;
+ }
+ safesnprintf( reason, 99, script_hasdata(st,2)? script_getstr(st,2) : " *maintenance off*" );
+ SQL->EscapeString( map->mysql_handle, esc_reason, reason );
+ if ( SQL->Query( map->mysql_handle, "insert into maintenance values ( null, 0, 'NPC', '%s', 0, null, now(), now() )", esc_reason ) == SQL_ERROR ) {
+ Sql_ShowDebug( map->mysql_handle );
+ return false;
+ }
+ chrif->maintenance_group = 0;
+ chrif->maintenance_starttime = (int)time(NULL);
+ chrif->maintenance_endtime = (int)time(NULL);
+ if ( chrif->maintenance_countid > INVALID_TIMER ) {
+ timer->delete( chrif->maintenance_countid, chrif->maintenance_countdown );
+ chrif->maintenance_countid = INVALID_TIMER;
+ }
+ if ( chrif->maintenance_timerid > INVALID_TIMER ) {
+ timer->delete( chrif->maintenance_timerid, chrif->maintenance_progress );
+ chrif->maintenance_timerid = INVALID_TIMER;
+ }
+ intif->broadcast2( "Maintenance mode has ended. Players are able to login now." , 255, battle_config.maintenance_color, 0x190, 12, 0, 0);
+ ShowStatus( CL_YELLOW "Maintenance has ended" CL_RESET ".\n" );
+ return true;
+}
+
+BUILDIN(maintenancecheck) {
+ int type = script_hasdata(st,2)? script_getnum(st,2) : 0;
+ switch( type ) {
+ default:
+ if ( chrif->maintenance_starttime > time(NULL) )
+ script_pushint(st, 1);
+ else if ( chrif->maintenance_endtime > time(NULL) )
+ script_pushint(st, 2);
+ else
+ script_pushint(st, 0);
+ return true;
+ case 1:
+ script_pushint(st, chrif->maintenance_group);
+ return true;
+ case 2:
+ script_pushint(st, chrif->maintenance_starttime);
+ return true;
+ case 3:
+ script_pushint(st, chrif->maintenance_endtime);
+ return true;
+ case 4:
+ script_pushint(st, chrif->maintenance_countid);
+ return true;
+ case 5:
+ script_pushint(st, chrif->maintenance_timerid);
+ return true;
+// case 6: // for some reason this cause memory leak
+// script_pushstr(st, chrif->maintenance_timeformat );
+// return true;
+ }
+}
+
#define BUILDIN_DEF(x,args) { buildin_ ## x , #x , args }
#define BUILDIN_DEF2(x,x2,args) { buildin_ ## x , x2 , args }
void script_parse_builtin(void) {
struct script_function BUILDIN[] = {
+ BUILDIN_DEF(maintenance,"iii?"),
+ BUILDIN_DEF(maintenanceoff,"?"),
+ BUILDIN_DEF(maintenancecheck,"?"),
// NPC interaction
BUILDIN_DEF(mes,"s*"),
BUILDIN_DEF(next,""),