//===== Hercules Plugin ======================================
//= @Maintenance mod
//===== By: ==================================================
//= AnnieRuru
//===== Current Version: =====================================
//= 1.4
//===== Compatible With: =====================================
//= Hercules 2015-12-08
//===== Description: =========================================
//= Turn the server into maintenance mode.
//= -> blocked players from login the game for a set of duration
//= a GM will announce the maintenance, and players will be kicked out after a while for maintenance.
//= Player below {Group ID can login} will not able to login for the duration
//= but GM99 can always login without restriction
//===== Topic ================================================
//= http://hercules.ws/board/topic/7127-
//===== Additional Comments: =================================
//= -- AtCommands --
//= @maintenance <Group ID can stay 1~99> <duration to kick in minute> <maintenance duration in minute> <reason>
//= @maintenanceoff
//=
//= -- Script Commands --
//= maintenance <Group ID can stay 1~99>, <duration to kick in minute>, <maintenance duration in minute> { , <reason> };
//= reason field is optional, default to '*Regular server maintenance*'
//= maintenanceoff { <reason> };
//= reason field is optional, default to '*maintenanceoff*'
//= maintenancecheck( <type> );
//= default:
//= return 0 if server is normal
//= return 1 if server is going to have maintenance
//= return 2 if server is having maintenance
//= type 1:
//= return the Group ID that has been denied to login
//= type 2:
//= return the time stamp of last/current starting time for the maintenance
//= type 3:
//= return the time stamp of last/current ending time for the maintenance
//= type 4:
//= return the ID of last used maintenance_countid ( for debugging only )
//= type 5:
//= return the ID of last used maintenance_timerid ( for debugging only )
//============================================================
/* Remember to build a Sql table !
create table maintenance (
id int(11) primary key auto_increment,
account_id int(11),
name varchar(23),
reason varchar(99),
minlv2connect tinyint(4),
order_time datetime,
start_time datetime,
end_time datetime
) engine = innodb;
*/
// change the announcement color
int maintenance_color = 0xFFFF00;
// If you still want to personalize each announcement to different color, just Ctrl+F 'maintenance_color' below
// ==========================================================
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "common/hercules.h"
#include "map/pc.h"
#include "map/map.h"
#include "map/intif.h"
#include "login/login.h"
#include "common/timer.h"
#include "common/strlib.h"
#include "common/memmgr.h"
#include "common/nullpo.h"
#include "common/sql.h"
#include "common/HPMDataCheck.h"
HPExport struct hplugin_info pinfo = {
"maintenance", // Plugin name
SERVER_TYPE_MAP,// Which server types this plugin works with?
"1.4", // Plugin version
HPM_VERSION, // HPM Version (don't change, macro is automatically updated)
};
int maintenance_group = 1;
int maintenance_starttime = 1;
int maintenance_endtime = 1;
int maintenance_countid = INVALID_TIMER;
int maintenance_timerid = INVALID_TIMER;
char maintenance_timeformat[24];
int maintenance_progress( int tid, int64 tick, int id, intptr data ) {
char output[CHAT_SIZE_MAX];
timer->delete( maintenance_timerid, maintenance_progress );
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, maintenance_color, 0x190, 12, 0, 0);
maintenance_group = 0;
maintenance_starttime = (int)time(NULL);
maintenance_endtime = (int)time(NULL);
ShowStatus( CL_YELLOW "Maintenance has ended." CL_RESET "\n" );
return false;
}
int maintenance_countdown( int tid, int64 tick, int id, intptr data ) {
char output[CHAT_SIZE_MAX];
int countdown = maintenance_starttime - (int)time(NULL);
if ( countdown > 90 ) {
safesnprintf( output, CHAT_SIZE_MAX, "Maintenance will start in %d minutes", countdown /60 );
intif->broadcast2( output, strlen(output) +1, maintenance_color, 0x190, 12, 0, 0);
timer->delete( maintenance_countid, maintenance_countdown );
if ( ( countdown % 60 ) > 0 ) // fine tune the timer
maintenance_countid = timer->add( timer->gettick() + ( ( countdown % 60 ) * 1000 ), maintenance_countdown, 0, 0 );
else
maintenance_countid = timer->add( timer->gettick() + 60000, maintenance_countdown, 0, 0 );
}
else if ( countdown > 15 ) {
safesnprintf( output, CHAT_SIZE_MAX, "Maintenance will start in %d seconds", countdown );
intif->broadcast2( output, strlen(output) +1, maintenance_color, 0x190, 12, 0, 0);
timer->delete( maintenance_countid, maintenance_countdown );
if ( ( countdown % 10 ) > 0 ) // fine tune the timer
maintenance_countid = timer->add( timer->gettick() + ( ( countdown % 10 ) * 1000 ), maintenance_countdown, 0, 0 );
else
maintenance_countid = timer->add( timer->gettick() + 10000, maintenance_countdown, 0, 0 );
}
else if ( countdown > 0 ) {
safesnprintf( output, CHAT_SIZE_MAX, "Maintenance will start in %d seconds", countdown );
intif->broadcast2( output, strlen(output) +1, maintenance_color, 0x190, 12, 0, 0);
timer->delete( maintenance_countid, maintenance_countdown );
maintenance_countid = timer->add( timer->gettick() + 1000, maintenance_countdown, 0, 0 );
}
else {
struct s_mapiterator* iter = mapit->alloc( MAPIT_NORMAL, BL_PC );
TBL_PC *sd;
safesnprintf( output, CHAT_SIZE_MAX, "Maintenance starts now. Every player will be kick out." );
intif->broadcast2( output, strlen(output) +1, 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 < maintenance_group )
clif->authfail_fd( sd->fd, 1 );
mapit->free(iter);
timer->delete( maintenance_countid, maintenance_countdown );
maintenance_countid = INVALID_TIMER;
maintenance_timerid = timer->add( timer->gettick() + ( ( maintenance_endtime - maintenance_starttime )*1000 ), maintenance_progress, 0, 0 );
ShowStatus( CL_YELLOW "Maintenance has started." CL_RESET "\n" );
}
return false;
}
HPExport void server_online (void) {
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 ) {
char *data;
short weekday = 0, hour = 0, minute = 0;
char* weekdayname[7] = { "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" };
char am_pm[3], min_display[3];
if ( SQL->GetData( map->mysql_handle, 0, &data, NULL ) == SQL_SUCCESS )
maintenance_group = atoi(data);
if ( SQL->GetData( map->mysql_handle, 1, &data, NULL ) == SQL_SUCCESS )
maintenance_starttime = atoi(data);
if ( SQL->GetData( map->mysql_handle, 2, &data, NULL ) == SQL_SUCCESS )
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( maintenance_timeformat, 24, "%s, %d:%s %s", weekdayname[ weekday ], hour, min_display, am_pm );
}
if ( maintenance_starttime > (int)time(NULL) ) {
int countdown = maintenance_starttime - (int)time(NULL);
if ( countdown > 60 )
maintenance_countid = timer->add( timer->gettick() + ( ( countdown % 60 )*1000 ), maintenance_countdown, 0, 0 );
else
maintenance_countid = timer->add( timer->gettick() + 1000, maintenance_countdown, 0, 0 );
ShowStatus( CL_YELLOW "Maintenance will start in %d min %d sec." CL_RESET "\n", countdown /60, countdown %60 );
}
else if ( maintenance_endtime > (int)time(NULL) ) {
int countdown = maintenance_endtime - (int)time(NULL);
maintenance_timerid = timer->add( timer->gettick() + ( countdown *1000 ), maintenance_progress, 0, 0 );
ShowStatus( CL_YELLOW "Maintenance will end in %d min %d sec on %s." CL_RESET "\n", countdown/60, countdown %60, maintenance_timeformat );
}
}
bool pc_authok_pre( struct map_session_data *sd, int *login_id2, time_t *expiration_time, int *group_id, struct mmo_charstatus *st, bool *changing_mapservers ) {
nullpo_retr( false, sd );
if ( (int)time(NULL) > maintenance_starttime && maintenance_endtime > (int)time(NULL) && *group_id < maintenance_group ) {
clif->authfail_fd( sd->fd, 1 );
hookStop();
return false;
}
return true;
}
void clif_parse_LoadEndAck_pre( int *fd, struct map_session_data *sd ) {
nullpo_retv(sd);
if ( sd->state.connect_new ) {
if ( maintenance_starttime > (int)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", ( maintenance_starttime - (int)time(NULL) ) /60, ( maintenance_starttime - (int)time(NULL) ) %60, ( maintenance_endtime - maintenance_starttime ) /60, maintenance_timeformat );
clif->message( sd->fd, output );
}
else if ( maintenance_endtime > (int)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", ( maintenance_endtime - (int)time(NULL) ) /60, ( maintenance_endtime - (int)time(NULL) ) %60, maintenance_timeformat );
clif->message( sd->fd, output );
}
}
return;
}
ACMD(maintenance) {
int group_id = 0, kick_duration = 0, maintenance_duration = 0;
char reason[99], esc_reason[198], esc_name[46], min_display[3], output[CHAT_SIZE_MAX];
short weekday = 0, hour = 0, minute = 0;
if ( maintenance_starttime > (int)time(NULL) ) {
int countdown = maintenance_starttime - (int)time(NULL);
clif->message( sd->fd, "Type '@maintenanceoff' to turn off maintenance mode." );
safesnprintf( output, CHAT_SIZE_MAX, "Maintenance mode will start in %d min %d sec.", countdown /60, countdown %60 );
clif->message( sd->fd, output );
return true;
}
if ( maintenance_endtime > (int)time(NULL) ) {
int countdown = maintenance_endtime - (int)time(NULL);
clif->message( sd->fd, "Type '@maintenanceoff' to turn off maintenance mode." );
safesnprintf( output, CHAT_SIZE_MAX, "Server is currently in maintenance mode, will end in %d min %d sec on %s", countdown /60, countdown %60, maintenance_timeformat );
clif->message( sd->fd, output );
return true;
}
if ( !message || !*message ) {
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;
}
// WTF ! sscanf can't be used ??
// if ( sscanf( message, "%d %d %d %99[^\n]", &group_id, &kick_duration, &maintenance_duration, &reason ) < 4 ) {
// 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;
// }
// now has to do the stupid string calculation
{
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( sd->fd, "The Group ID field cannot be 0, otherwise normal player able to login." );
return false;
}
if ( group_id < 1 || group_id > 99 ) {
safesnprintf( output, 255, "Invalid Group ID %d. Range must between 1~99.", group_id );
clif->message( sd->fd, output );
return false;
}
if ( kick_duration <= 0 ) {
clif->message( sd->fd, "Kick duration cannot be 0 or negative numbers." );
return false;
}
if ( kick_duration > 1440 ) {
clif->message( sd->fd, "Kick duration cannot be more than 1 day." );
return false;
}
if ( maintenance_duration <= 0 ) {
clif->message( sd->fd, "Maintenance duration cannot be 0 or negative numbers." );
return false;
}
if ( maintenance_duration > 10080 ) {
clif->message( sd->fd, "Maintenance duration cannot be more than 1 week." );
return false;
}
if ( safestrnlen( reason, 99 ) < 4 ) {
clif->message( sd->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;
maintenance_group = group_id;
if ( SQL->GetData( map->mysql_handle, 0, &data, NULL ) == SQL_SUCCESS )
maintenance_starttime = atoi(data);
if ( SQL->GetData( map->mysql_handle, 1, &data, NULL ) == SQL_SUCCESS )
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( 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, maintenance_timeformat );
intif->broadcast2( output, strlen(output) +1, maintenance_color, 0x190, 12, 0, 0);
}
maintenance_countid = timer->add( timer->gettick() +( ( kick_duration == 1 )? 1000 : 60000 ), 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], output[CHAT_SIZE_MAX];
if ( maintenance_endtime <= (int)time(NULL) ) {
clif->message( sd->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;
}
maintenance_group = 0;
maintenance_starttime = (int)time(NULL);
maintenance_endtime = (int)time(NULL);
if ( maintenance_countid != INVALID_TIMER ) {
timer->delete( maintenance_countid, maintenance_countdown );
maintenance_countid = INVALID_TIMER;
}
if ( maintenance_timerid != INVALID_TIMER ) {
timer->delete( maintenance_timerid, maintenance_progress );
maintenance_timerid = INVALID_TIMER;
}
safesnprintf( output, CHAT_SIZE_MAX, "%s ended the Maintenance mode. Players are able to login now.", sd->status.name );
intif->broadcast2( output, strlen(output) +1, maintenance_color, 0x190, 12, 0, 0);
ShowStatus( CL_YELLOW "Maintenance has ended by " CL_GREEN "%s" CL_RESET ".\n", sd->status.name );
return 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 ( maintenance_endtime > (int)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;
maintenance_group = group_id;
if ( SQL->GetData( map->mysql_handle, 0, &data, NULL ) == SQL_SUCCESS )
maintenance_starttime = atoi(data);
if ( SQL->GetData( map->mysql_handle, 1, &data, NULL ) == SQL_SUCCESS )
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( 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, maintenance_timeformat );
intif->broadcast2( output, strlen(output) +1, maintenance_color, 0x190, 12, 0, 0);
}
maintenance_countid = timer->add( timer->gettick() +( ( kick_duration == 1 )? 1000 : 60000 ), 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 ( maintenance_endtime <= (int)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;
}
maintenance_group = 0;
maintenance_starttime = (int)time(NULL);
maintenance_endtime = (int)time(NULL);
if ( maintenance_countid != INVALID_TIMER ) {
timer->delete( maintenance_countid, maintenance_countdown );
maintenance_countid = INVALID_TIMER;
}
if ( maintenance_timerid != INVALID_TIMER ) {
timer->delete( maintenance_timerid, maintenance_progress );
maintenance_timerid = INVALID_TIMER;
}
intif->broadcast2( "Maintenance mode has ended. Players are able to login now." , 255, 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 ( maintenance_starttime > (int)time(NULL) )
script_pushint(st, 1);
else if ( maintenance_endtime > (int)time(NULL) )
script_pushint(st, 2);
else
script_pushint(st, 0);
return true;
case 1:
script_pushint(st, maintenance_group);
return true;
case 2:
script_pushint(st, maintenance_starttime);
return true;
case 3:
script_pushint(st, maintenance_endtime);
return true;
case 4:
script_pushint(st, maintenance_countid);
return true;
case 5:
script_pushint(st, maintenance_timerid);
return true;
// case 6: // for some reason this cause memory leak
// script_pushstr(st, maintenance_timeformat );
// return true;
}
}
HPExport void plugin_init (void) {
addHookPre( "pc->authok", pc_authok_pre );
addHookPre( "clif->pLoadEndAck", clif_parse_LoadEndAck_pre );
addAtcommand( "maintenance", maintenance );
addAtcommand( "maintenanceoff", maintenanceoff );
addScriptCommand( "maintenance", "iii?", maintenance );
addScriptCommand( "maintenanceoff", "?", maintenanceoff );
addScriptCommand( "maintenancecheck", "?", maintenancecheck );
}
partyscript.c
// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
// See the LICENSE file
// Mhalicot PartyScript Hercules Plugin
// Special Thanks for Mr. [Hercules/Ind]
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "common/HPMi.h"
#include "common/cbasetypes.h"
#include "common/strlib.h"
#include "common/utils.h"
#include "common/malloc.h"
#include "common/mmo.h"
#include "common/db.h"
#include "map/atcommand.h"
#include "map/script.h"
#include "map/party.h"
#include "map/intif.h"
#include "map/status.h"
#include "map/clif.h"
#include "map/map.h"
#include "map/mapreg.h"
#include "map/pc.h"
#include "map/instance.h"
#include "common/HPMDataCheck.h"/* should always be the last file included! (if you don't make it last, it'll intentionally break compile time) */
#define party_add_member(party_id,sd) party_reply_invite_mine(sd,party_id,1)
#define safestrncpy(dst,src,n) (strlib->safestrncpy((dst),(src),(n)))
#define idb_remove(db,k) ( (db)->remove((db),DB->i2key(k),NULL) )
/*
1.0 Initial HPM Release [Mhalicot]
1.1 Rewrite party_delmember, removemember2 dropped.
1.2 Update Compatibility to latest Revision 137**
2.0 Update codes, Drop some useless codes.
2.1 Fixed Map crash when using designate in Party Window
2.2 Resolved crashing issue when leaving party from instance. [Mumbles / Haru]
3.0 Added @leaveparty Command [Mhalicot]
3.1 Fixed Various Compile Warnings and some logic [Dastgir]
---------------------------------------
Documentation
---------------------------------------
*party_create("<party name>"{,<character id>{,<item share>,<item share type>}});
Organizes a party with the attached or specified character as leader. If
successful, the command returns 1 and sets the global temporary variable
"$@party_create_id" to the ID of the party created.
Additionally, item sharing options can be provided:
- Item Share: 0-Each Take (default), 1-Party Share
- Item Share Type: 0-Each Take (default), 1-Even Share
These values are returned upon failure:
0: Unknown error.
-1: Player not found.
-2: Player already has a party.
-3: Party name exists.
---------------------------------------
*party_destroy(<party id>);
Disbands a party. The command returns 1 upon success and 0 upon failure.
---------------------------------------
*party_addmember(<party id>,<character id>);
Adds a player to an existing party.
The command returns 1 upon success, and these values upon failure:
0: Unknown error.
-1: Player not found.
-2: Player already has a party.
-3: Party not found.
-4: Party is full.
---------------------------------------
*party_delmember({<character id>});
Removes a player from his/her party. If no player is specified, the command
will run for the invoking player. If that player is the only party member
remaining, the party will be disbanded.
The command returns 1 upon success, and these values upon failure:
0: Unknown error.
-1: Player not found.
-2: Player is not in the party.
---------------------------------------
*party_changeleader(<party id>,<character id>);
Transfers leadership of a party to the specified character. The original
party leader doesn't need be online.
The command returns 1 upon success, and these values upon failure:
0: Unknown error.
-1: Party not found.
-2: Player not found.
-3: Player is not in the party.
-4: Player is already party leader
---------------------------------------
*party_changeoption(<party id>,<option>,<flag>);
Changes a party option.
Valid options are:
0 - Exp Share (flags: 0-Each Take, 1-Even Share)
1 - Item Share (flags: 0-Each Take, 1-Party Share)
2 - Item Share Type (flags: 0-Each Take, 1-Even Share)
The command returns 1 upon success, and these values upon failure:
0: Invalid option.
-1: Party not found.
*/
HPExport struct hplugin_info pinfo = {
"partyscript", // Plugin name
SERVER_TYPE_MAP, // Which server types this plugin works with?
"2.2", // Plugin version
HPM_VERSION, // HPM Version (don't change, macro is automatically updated)
};
int create_byscript;
int party_change_leader_val = 0;
struct party_data *party_change_leader_p = NULL;
int party_create_mine(struct map_session_data *sd,char *name,int item,int item2) {
struct party_member leader;
char tname[NAME_LENGTH];
safestrncpy(tname, name, NAME_LENGTH);
trim(tname);
if( !tname[0] ) {// empty name
return 0;
}
if( sd->status.party_id > 0 || sd->party_joining || sd->party_creating ) {// already associated with a party
clif->party_created(sd,2);
return -2;
}
sd->party_creating = true;
party->fill_member(&leader, sd, 1);
intif->create_party(&leader,name,item,item2);
return 1;
}
void party_created_mine(int account_id,int char_id,int fail,int party_id,char *name) {
struct map_session_data *sd;
sd=map->id2sd(account_id);
if (!sd || sd->status.char_id != char_id || !sd->party_creating ) {
//Character logged off before creation ack?
if (!fail) //break up party since player could not be added to it.
intif->party_leave(party_id,account_id,char_id);
return;
}
sd->party_creating = false;
if( !fail ) {
sd->status.party_id = party_id;
clif->party_created(sd,0); //Success message
//We don't do any further work here because the char-server sends a party info packet right after creating the party
if(create_byscript) { //returns party id in $@party_create_id if party is created by script
mapreg->setreg(script->add_str("$@party_create_id"),party_id);
create_byscript = 0;
}
} else
clif->party_created(sd,1); // "party name already exists"
}
int party_reply_invite_mine(struct map_session_data *sd,int party_id,int flag) {
struct map_session_data* tsd;
struct party_member member;
if( sd->party_invite != party_id ) {// forged
sd->party_invite = 0;
sd->party_invite_account = 0;
return 0;
}
tsd = map->id2sd(sd->party_invite_account);
if( flag == 1 && !sd->party_creating && !sd->party_joining ) {// accepted and allowed
sd->party_joining = true;
party->fill_member(&member, sd, 0);
intif->party_addmember(sd->party_invite, &member);
return 1;
} else {// rejected or failure
sd->party_invite = 0;
sd->party_invite_account = 0;
if( tsd != NULL )
clif->party_inviteack(tsd,sd->status.name,1);
return 0;
}
return 0;
}
void party_reply_invite_overload(struct map_session_data *sd,int party_id,int flag) {
party_reply_invite_mine(sd,party_id,flag);
}
//options: 0-exp, 1-item share, 2-pickup distribution
int party_setoption(struct party_data *pdata, int option, int flag) {
int i;
ARR_FIND(0,MAX_PARTY,i,pdata->party.member[i].leader);
if(i >= MAX_PARTY)
return 0;
switch(option) {
case 0:
intif->party_changeoption(pdata->party.party_id,pdata->party.member[i].account_id,flag,pdata->party.item);
break;
case 1:
if(flag) flag = pdata->party.item|1;
else flag = pdata->party.item&~1;
intif->party_changeoption(pdata->party.party_id,pdata->party.member[i].account_id,pdata->party.exp,flag);
break;
case 2:
if(flag) flag = pdata->party.item|2;
else flag = pdata->party.item&~2;
intif->party_changeoption(pdata->party.party_id,pdata->party.member[i].account_id,pdata->party.exp,flag);
break;
default:
return 0;
break;
}
return 1;
}
bool party_changeleader_mine(struct map_session_data *sd, struct map_session_data *tsd) {
int mi, tmi;
struct party_data *p = party_change_leader_p;
party_change_leader_p = NULL;
if ( !p ) {
if (!sd || !sd->status.party_id) {
party_change_leader_val = -1;
return false;
}
if (!tsd || tsd->status.party_id != sd->status.party_id) {
clif->message(sd->fd, "Target character must be online and in your current party.");
party_change_leader_val = -3;
return false;
}
if ( map->list[sd->bl.m].flag.partylock ) {
clif->message(sd->fd, "You cannot change party leaders on this map.");
party_change_leader_val = 0;
return false;
}
if ((p = party->search(sd->status.party_id)) == NULL ) {
party_change_leader_val = -1;
return false;
}
ARR_FIND( 0, MAX_PARTY, mi, p->data[mi].sd == sd );
if (mi == MAX_PARTY) {
party_change_leader_val = 0; //Shouldn't happen
return false;
}
if (!p->party.member[mi].leader) {
clif->message(sd->fd, "You need to be a party leader to use this command.");
party_change_leader_val = 0;
return false;
}
ARR_FIND( 0, MAX_PARTY, tmi, p->data[tmi].sd == tsd);
if (tmi == MAX_PARTY) {
party_change_leader_val = 0; //Shouldn't happen
return false;
}
} else {
ARR_FIND(0,MAX_PARTY,mi,p->party.member[mi].leader);
ARR_FIND(0,MAX_PARTY,tmi,p->data[tmi].sd == tsd);
}
if (!p->party.member[mi].leader) {
clif->message(sd->fd, "You need to be a party leader to use this command.");
party_change_leader_val = 0;
return false;
}
ARR_FIND( 0, MAX_PARTY, tmi, p->data[tmi].sd == tsd);
if (tmi == MAX_PARTY) {
party_change_leader_val = 0; //Shouldn't happen
return false;
}
//Change leadership.
p->party.member[mi].leader = 0;
if (p->data[mi].sd && p->data[mi].sd->fd)
clif->message(p->data[mi].sd->fd, "Leadership transferred.");
p->party.member[tmi].leader = 1;
if (p->data[tmi].sd && p->data[tmi].sd->fd)
clif->message(p->data[tmi].sd->fd, "You've become the party leader.");
//Update info.
intif->party_leaderchange(p->party.party_id,p->party.member[tmi].account_id,p->party.member[tmi].char_id);
clif->party_info(p,NULL);
party_change_leader_val = 1;
return true;
}
/*==========================================
* party_create "<party name>"{,<char id>{,<item share: 0-no. 1-yes>{,<item share type: 0-favorite. 1-shared>}}};
* Return values:
* -3 - party name is exist
* -2 - player is in party already
* -1 - player is not found
* 0 - unknown error
* 1 - success, will return party id $@party_create_id
*------------------------------------------*/
BUILDIN(party_create) {
char party_name[NAME_LENGTH];
int item1 = 0, item2 = 0;
TBL_PC *sd = NULL;
if( (!script_hasdata(st,3) && !(sd = script->rid2sd(st))) || (script_hasdata(st,3) && !(sd = map->charid2sd(script_getnum(st,3)))) ) {
script_pushint(st,-1);
return false;
}
if( sd->status.party_id ) {
script_pushint(st,-2);
return false;
}
safestrncpy(party_name,script_getstr(st,2),NAME_LENGTH);
trim(party_name);
if( party->searchname(party_name) ) {
script_pushint(st,-3);
return false;
}
if( script_getnum(st,4) )
item1 = 1;
if( script_getnum(st,5) )
item2 = 1;
create_byscript = 1;
script_pushint(st,party_create_mine(sd,party_name,item1,item2));
return true;
}
/*==========================================
* party_addmember <party id>,<char id>;
* Adds player to specified party
* Return values:
* -4 - party is full
* -3 - party is not found
* -2 - player is in party already
* -1 - player is not found
* 0 - unknown error
* 1 - success
*------------------------------------------*/
BUILDIN(party_addmember) {
int party_id = script_getnum(st,2);
TBL_PC *sd;
struct party_data *pty;
if( !(sd = map->charid2sd(script_getnum(st,3))) ) {
script_pushint(st,-1);
return false;
}
if( sd->status.party_id ) {
script_pushint(st,-2);
return false;
}
if( !(pty = party->search(party_id)) ) {
script_pushint(st,-3);
return false;
}
if( pty->party.count >= MAX_PARTY ) {
script_pushint(st,-4);
return false;
}
sd->party_invite = party_id;
script_pushint(st,party_add_member(party_id,sd));
return true;
}
/*==========================================
* party_delmember {<char id>};
* Removes player from his/her party
* Return values:
* -2 - player is not in party
* -1 - player is not found
* 0 - unknown error
* 1 - success
*------------------------------------------*/
BUILDIN(party_delmember) {
TBL_PC *sd = NULL;
if( (!script_hasdata(st,2) && !(sd = script->rid2sd(st))) ||
(script_hasdata(st,2) && !(sd = map->charid2sd(script_getnum(st,2))))
){
script_pushint(st,-1);
return false;
}
if( !sd->status.party_id ) {
script_pushint(st,-2);
return false;
}
script_pushint(st,party->leave(sd));
return true;
}
/*==========================================
* party_changeleader <party id>,<char id>;
* Can change party leader even the leader is not online
* Return values:
* -4 - player is party leader already
* -3 - player is not in this party
* -2 - player is not found
* -1 - party is not found
* 0 - unknown error
* 1 - success
*------------------------------------------*/
BUILDIN(party_changeleader) {
int i, party_id = script_getnum(st,2);
TBL_PC *sd = NULL;
TBL_PC *tsd = NULL;
struct party_data *pty = NULL;
if( !(pty = party->search(party_id)) ) {
script_pushint(st,-1);
return false;
}
if( !(tsd = map->charid2sd(script_getnum(st,3))) ) {
script_pushint(st,-2);
return false;
}
if( tsd->status.party_id != party_id ) {
script_pushint(st,-3);
return false;
}
ARR_FIND(0,MAX_PARTY,i,pty->party.member[i].leader);
if( i >= MAX_PARTY ) { //this is should impossible!
script_pushint(st,0);
return false;
}
if( pty->data[i].sd == tsd ) {
script_pushint(st,-4);
return false;
}
party_change_leader_p = pty;
party_changeleader_mine(sd,tsd);
script_pushint(st,party_change_leader_val);
return true;
}
/*==========================================
* party_changeoption <party id>,<option>,<flag>;
* Return values:
* -1 - party is not found
* 0 - invalid option
* 1 - success
*------------------------------------------*/
BUILDIN(party_changeoption) {
struct party_data *pty;
if( !(pty = party->search(script_getnum(st,2))) ) {
script_pushint(st,-1);
return true;
}
script_pushint(st,party_setoption(pty,script_getnum(st,3),script_getnum(st,4)));
return true;
}
/*==========================================
* party_destroy <party id>;
* Destroys party with party id.
* Return values:
* 0 - failed
* 1 - success
*------------------------------------------*/
BUILDIN(party_destroy) {
int i;
struct party_data *pty;
if( !(pty = party->search(script_getnum(st,2))) ) {
script_pushint(st,0);
}
ARR_FIND(0,MAX_PARTY,i,pty->party.member[i].leader);
if( i >= MAX_PARTY || !pty->data[i].sd ) { //leader not online
int j;
for( j = 0; j < MAX_PARTY; j++ ) {
TBL_PC *sd = pty->data[j].sd;
if(sd)
party->member_withdraw(pty->party.party_id,sd->status.account_id,sd->status.char_id);
else if( pty->party.member[j].char_id )
intif->party_leave(pty->party.party_id,pty->party.member[j].account_id,pty->party.member[j].char_id);
}
//party_broken_mine(pty->party.party_id);
party->broken(pty->party.party_id);
script_pushint(st,1);
}
else //leader leave = party broken
script_pushint(st,party->leave(pty->data[i].sd));
return true;
}
/*==========================================
*
*------------------------------------------*/
ACMD(party) {
char party_name[NAME_LENGTH];
memset(party_name, '\0', sizeof(party_name));
if (!message || !*message || sscanf(message, "%23[^\n]", party_name) < 1) {
clif->message(fd, "Please enter a party name (usage: @party <party_name>).");
return false;
}
party_create_mine(sd, party_name, 0, 0);
return true;
}
ACMD(leaveparty) {
if( !sd->status.party_id ) {
clif->message(fd, "You must have a party to use this command");
return false;
}
party->leave(sd);
return true;
}
ACMD(partyoption) {
struct party_data *p;
int mi, option;
char w1[16], w2[16];
if (sd->status.party_id == 0 || (p = party->search(sd->status.party_id)) == NULL) {
clif->message(fd, "You need to be a party leader to use this command.");
return false;
}
ARR_FIND( 0, MAX_PARTY, mi, p->data[mi].sd == sd );
if (mi == MAX_PARTY)
return false; //Shouldn't happen
if (!p->party.member[mi].leader) {
clif->message(fd, "You need to be a party leader to use this command.");
return false;
}
if(!message || !*message || sscanf(message, "%15s %15s", w1, w2) < 2) {
clif->message(fd, "Usage: @partyoption <pickup share: yes/no> <item distribution: yes/no>");
return false;
}
option = (config_switch(w1)?1:0)|(config_switch(w2)?2:0);
//Change item share type.
if (option != p->party.item)
party->changeoption(sd, p->party.exp, option);
else
clif->message(fd, "There's been no change in the setting.");
return true;
}
/* Server Startup */
HPExport void plugin_init (void) {
instance = GET_SYMBOL("instance");
script = GET_SYMBOL("script");
mapreg = GET_SYMBOL("mapreg");
strlib = GET_SYMBOL("strlib");
party = GET_SYMBOL("party");
intif = GET_SYMBOL("intif");
clif = GET_SYMBOL("clif");
map = GET_SYMBOL("map");
DB = GET_SYMBOL("DB");
//Commands
addAtcommand("partyoption",partyoption);
addAtcommand("leaveparty",leaveparty);
addAtcommand("party",party);
//Scripts
addScriptCommand("party_changeoption","iii",party_changeoption);
addScriptCommand("party_changeleader","ii",party_changeleader);
addScriptCommand("party_addmember","ii",party_addmember);
addScriptCommand("party_delmember","?",party_delmember);
addScriptCommand("party_create","s???",party_create);
addScriptCommand("party_destroy","i",party_destroy);
party->changeleader = &party_changeleader_mine;
party->reply_invite = &party_reply_invite_overload;
party->created = &party_created_mine;
party->create = &party_create_mine;
};
noitem.c
//===== Hercules Plugin ======================================
//= noitem mapflag
//===== By: ==================================================
//= AnnieRuru
//===== Current Version: =====================================
//= 1.3
//===== Compatible With: =====================================
//= Hercules 2015-11-12
//===== Description: =========================================
//= block players from using items
//===== Topic ================================================
//= http://herc.ws/board/topic/4830-noitem-mapflag/
//===== Additional Comments: =================================
//= prontera mapflag noitem IT_WEAPON,IT_ARMOR
//= block players from equipping weapon and armor
//============================================================
#include "common/hercules.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "map/pc.h"
#include "common/memmgr.h"
#include "common/HPMDataCheck.h"
HPExport struct hplugin_info pinfo = {
"noitem", // Plugin name
SERVER_TYPE_MAP,// Which server types this plugin works with?
"1.3", // Plugin version
HPM_VERSION, // HPM Version (don't change, macro is automatically updated)
};
struct mapflag_data {
int noitem;
int noitemlist[50];
};
// flush all noitem mapflag back to default upon @reloadscript
void map_flags_init_pre(void) {
int i;
for ( i = 0; i < map->count; i++ ) {
struct mapflag_data *mf = getFromMAPD( &map->list[i], 0 );
if ( mf )
removeFromMAPD( &map->list[i], 0 );
}
return;
}
void npc_parse_unknown_mapflag_pre( const char *name, char *w3, char *w4, const char* start, const char* buffer, const char* filepath, int *retval ) {
if ( !strcmp(w3,"noitem") ) {
int id = 0, i = 0, j = 0, k = 0, l = strlen(w4);
char *temp = (char*)aMalloc( strlen(w4) +1 );
struct item_data *i_data;
struct mapflag_data *mf;
if ( l ) {
int16 m = map->mapname2mapid( name );
CREATE( mf, struct mapflag_data, 1 );
while ( i <= l && k < 50 ) {
if ( w4[i] != ' ' && w4[i] != ' ' && w4[i] != ',' && w4[i] != '\0' ) {
temp[j++] = w4[i];
}
else if ( w4[i-1] != ' ' && w4[i-1] != ' ' && w4[i-1] != ',' ) {
temp[j] = '\0';
if ( !strcmp( temp, "IT_HEALING" ) || !strcmp( temp, "0" ) )
mf->noitemlist[k] = 0;
else if ( !strcmp( temp, "IT_USABLE" ) || !strcmp( temp, "2" ) )
mf->noitemlist[k] = 2;
else if ( !strcmp( temp, "IT_WEAPON" ) || !strcmp( temp, "4" ) )
mf->noitemlist[k] = 4;
else if ( !strcmp( temp, "IT_ARMOR" ) || !strcmp( temp, "5" ) )
mf->noitemlist[k] = 5;
else if ( !strcmp( temp, "IT_CARD" ) || !strcmp( temp, "6" ) )
mf->noitemlist[k] = 6;
else if ( !strcmp( temp, "IT_DELAYCONSUME" ) || !strcmp( temp, "11" ) )
mf->noitemlist[k] = 11;
else if ( !strcmp( temp, "IT_CASH" ) || !strcmp( temp, "18" ) )
mf->noitemlist[k] = 18;
else if ( atoi(temp) == 0 ) {
i_data = itemdb->search_name( temp );
if ( i_data )
mf->noitemlist[k] = i_data->nameid;
else {
ShowWarning("npc_parse_mapflag: Item name \"%s\" does not exist.\n Mapflag noitem: At %s (file '%s', line '%d').\n", temp, name, filepath, strline(buffer,start-buffer) );
mf->noitemlist[k] = -1;
}
}
else {
id = atoi(temp);
if ( itemdb->exists(id) )
mf->noitemlist[k] = id;
else {
ShowWarning("npc_parse_mapflag: Item ID \"%s\" does not exist.\n Mapflag noitem: At %s (file '%s', line '%d').\n", temp, name, filepath, strline(buffer,start-buffer) );
mf->noitemlist[k] = -1;
}
}
k++;
j = 0;
}
i++;
}
mf->noitem = k;
addToMAPD( &map->list[m], mf, 0, true );
}
else
ShowWarning("npc_parse_mapflag: no Item ID/type input.\n Mapflag noitem: At %s (file '%s', line '%d').\n", name, filepath, strline(buffer,start-buffer));
aFree(temp);
hookStop();
}
return;
}
int pc_isequip_post( int retVal, struct map_session_data *sd, int *n ) {
if ( retVal == 1 ) {
struct mapflag_data *mf = getFromMAPD( &map->list[sd->bl.m], 0 );
if ( mf && mf->noitem ) {
struct item_data *item = sd->inventory_data[*n];
int i = 0, slot = 0;
ARR_FIND( 0, mf->noitem, i, item->nameid == mf->noitemlist[i] || item->type == mf->noitemlist[i] );
if ( i < mf->noitem )
return 0;
if ( !itemdb_isspecial( sd->status.inventory[*n].card[0] ) ) {
for ( slot = 0; slot < MAX_SLOTS; slot++ ) {
if ( sd->status.inventory[*n].card[slot] ) {
struct item_data *i_data = itemdb->exists( sd->status.inventory[*n].card[slot] );
ARR_FIND( 0, mf->noitem, i, i_data->nameid == mf->noitemlist[i] || i_data->type == mf->noitemlist[i] );
if ( i < mf->noitem )
return 0;
}
}
}
}
}
return retVal;
}
int pc_isUseitem_post( int retVal, struct map_session_data *sd, int *n ) {
if ( retVal == 1 ) {
struct mapflag_data *mf = getFromMAPD( &map->list[sd->bl.m], 0 );
if ( mf && mf->noitem ) {
struct item_data *item = sd->inventory_data[*n];
int i = 0;
ARR_FIND( 0, mf->noitem, i, mf->noitemlist[i] == sd->status.inventory[*n].nameid || item->type == mf->noitemlist[i] );
if ( i < mf->noitem )
return 0;
}
}
return retVal;
}
int pc_checkitem_post( int retVal, struct map_session_data *sd ) {
struct mapflag_data *mf = getFromMAPD( &map->list[sd->bl.m], 0 );
int i, calc_flag = 0;
if ( sd->state.vending )
return 0;
if ( mf && mf->noitem ) {
for ( i = 0; i < MAX_INVENTORY; i++ ) {
int j = 0, slot = 0;
struct item_data *i_data = itemdb->exists( sd->status.inventory[i].nameid );
if ( sd->status.inventory[i].nameid == 0 || !sd->status.inventory[i].equip )
continue;
ARR_FIND( 0, mf->noitem, j, mf->noitemlist[j] == i_data->type || mf->noitemlist[j] == sd->status.inventory[i].nameid );
if ( j < mf->noitem ) {
pc->unequipitem(sd, i, 2);
calc_flag = 1;
continue;
}
if ( !itemdb_isspecial( sd->status.inventory[i].card[0] ) ) {
for ( slot = 0; slot < MAX_SLOTS; slot++ ) {
if ( sd->status.inventory[i].card[slot] ) {
struct item_data *i_datac = itemdb->exists( sd->status.inventory[i].card[slot] );
ARR_FIND( 0, mf->noitem, j, mf->noitemlist[j] == i_datac->type || mf->noitemlist[j] == sd->status.inventory[i].card[slot] );
if ( j < mf->noitem ) {
pc->unequipitem(sd, i, 2);
calc_flag = 1;
break;
}
}
}
}
}
if ( calc_flag && sd->state.active ) {
pc->checkallowskill(sd);
status_calc_pc( sd,SCO_NONE );
}
}
return retVal;
}
HPExport void plugin_init (void) {
addHookPre( "map->flags_init", map_flags_init_pre );
addHookPre( "npc->parse_unknown_mapflag", npc_parse_unknown_mapflag_pre );
addHookPost( "pc->isequip", pc_isequip_post );
addHookPost( "pc->isUseitem", pc_isUseitem_post );
addHookPost( "pc->checkitem", pc_checkitem_post );
}
market.c
//===== Hercules Plugin ======================================
//= @market clone
//===== By: ==================================================
//= AnnieRuru
//= Credit - Dastgir -> http://hercules.ws/board/topic/7188-market/
//===== Current Version: =====================================
//= 1.5
//===== Compatible With: =====================================
//= Hercules 2016-1-1
//===== Description: =========================================
//= Create a market clone, to leave a message for other players
//= while the player can go hunting/questing/events
//===== Topic ================================================
//= http://hercules.ws/board/topic/7242-market-clone/
//===== Additional Comments: =================================
//= -- AtCommands --
//= @market "<Title>" "<Message>" <Color>
//= create a market clone with a chat room titled -> "<Title>"
//= when players tries to join the chat room, it refuse the joining, but instead leave a message -> "<Message>" <- with their own desired <Color>
//= @marketkill
//= kill the market clone without logging off
//=
//= a GM doing a @killmonster @killmonster2, or *killmonster *kilmonsterall script command will not remove the clone
//= but @reloadscript, however, will remove it
//============================================================
// how many seconds delay from creating another market clone ?
// Note: if you set it too low like 1 second, player might spawn the clone all over the town, unit->free doesn't act fast enough to remove them, 10 seconds is ideal
int market_clone_delay = 10; // 10 seconds
// the zeny cost for creating a market clone
int market_clone_zenycost = 0;
// if the player has cart/riding/ward/falcon, will these objects cloned as well ?
int market_clone_companion = 0; // set to 1 to enable
//============================================================
#include "common/hercules.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "map/pc.h"
#include "map/mob.h"
#include "map/npc.h"
#include "map/chat.h"
#include "map/clif.h"
#include "map/guild.h"
#include "map/skill.h"
#include "map/unit.h"
#include "map/battle.h"
#include "common/memmgr.h"
#include "common/strlib.h"
#include "common/socket.h"
#include "plugins/HPMHooking.h"
#include "common/HPMDataCheck.h"
HPExport struct hplugin_info pinfo = {
"marketclone",
SERVER_TYPE_MAP,
"1.5",
HPM_VERSION,
};
struct player_data {
int market_clone_id;
int market_clone_delay;
};
struct monster_data {
int uid;
int market_pushcart;
int market_chat_id;
int market_msg_color;
char market_message[CHAT_SIZE_MAX];
};
void color_list(int fd) {
clif->messagecolor_self(fd, 0x00FFFF, "0 - Aqua (default)");
clif->messagecolor_self(fd, 0x000001, "1 - Black");
clif->messagecolor_self(fd, 0x0000FF, "2 - Blue");
clif->messagecolor_self(fd, 0x808080, "3 - Grey");
clif->messagecolor_self(fd, 0x008000, "4 - Green");
clif->messagecolor_self(fd, 0x00FF00, "5 - Lime");
clif->messagecolor_self(fd, 0x800000, "6 - Maroon");
clif->messagecolor_self(fd, 0x000080, "7 - Navy");
clif->messagecolor_self(fd, 0x808000, "8 - Olive");
clif->messagecolor_self(fd, 0xFFA500, "9 - Orange");
clif->messagecolor_self(fd, 0x800080, "10 - Purple");
clif->messagecolor_self(fd, 0xFF0000, "11 - Red");
clif->messagecolor_self(fd, 0xC0C0C0, "12 - Silver");
clif->messagecolor_self(fd, 0x008080, "13 - Teal");
clif->messagecolor_self(fd, 0xFFFFFF, "14 - White");
clif->messagecolor_self(fd, 0xFFC0CB, "15 - Pink");
clif->messagecolor_self(fd, 0xD2691E, "16 - Chocolate");
clif->messagecolor_self(fd, 0xFFD700, "17 - Gold");
clif->messagecolor_self(fd, 0xEE82EE, "18 - Violet");
return;
}
// I was thinking of using array before ... but I guess, this kind of implementation is easier for you guys to add custom color
// if want to remove a color, just comment/delete that line. If want to add, well, you can guess the format XD
void color_message(int fd, int msg_color, char market_msg[]) {
switch (msg_color) {
default: clif->messagecolor_self(fd, 0x00FFFF, market_msg); break;
case 1: clif->messagecolor_self(fd, 0x000001, market_msg); break;
case 2: clif->messagecolor_self(fd, 0x0000FF, market_msg); break;
case 3: clif->messagecolor_self(fd, 0x808080, market_msg); break;
case 4: clif->messagecolor_self(fd, 0x008000, market_msg); break;
case 5: clif->messagecolor_self(fd, 0x00FF00, market_msg); break;
case 6: clif->messagecolor_self(fd, 0x800000, market_msg); break;
case 7: clif->messagecolor_self(fd, 0x000080, market_msg); break;
case 8: clif->messagecolor_self(fd, 0x808000, market_msg); break;
case 9: clif->messagecolor_self(fd, 0xFFA500, market_msg); break;
case 10: clif->messagecolor_self(fd, 0x800080, market_msg); break;
case 11: clif->messagecolor_self(fd, 0xFF0000, market_msg); break;
case 12: clif->messagecolor_self(fd, 0xC0C0C0, market_msg); break;
case 13: clif->messagecolor_self(fd, 0x008080, market_msg); break;
case 14: clif->messagecolor_self(fd, 0xFFFFFF, market_msg); break;
case 15: clif->messagecolor_self(fd, 0xFFC0CB, market_msg); break;
case 16: clif->messagecolor_self(fd, 0xD2691E, market_msg); break;
case 17: clif->messagecolor_self(fd, 0xFFD700, market_msg); break;
case 18: clif->messagecolor_self(fd, 0xEE82EE, market_msg); break;
}
return;
}
int mob_clone_spawn_market(struct map_session_data *sd, int16 m, int16 x, int16 y, char market_title[], char market_msg[], int msg_color) { //Copy of mob_clone_spawn with some modification.
int class_;
struct mob_data *md;
struct monster_data *mmd;
struct mob_db* db;
struct status_data *mstatus;
struct chat_data* cd;
ARR_FIND(MOB_CLONE_START, MOB_CLONE_END, class_, mob->db_data[class_] == NULL);
if (class_ >= MOB_CLONE_END)
return 0;
db = mob->db_data[class_] = (struct mob_db*)aCalloc(1, sizeof(struct mob_db));
mstatus = &db->status;
safestrncpy(db->sprite, sd->status.name, NAME_LENGTH);
safestrncpy(db->name, sd->status.name, NAME_LENGTH);
safestrncpy(db->jname, sd->status.name, NAME_LENGTH);
db->lv = status->get_lv(&sd->bl);
memcpy(mstatus, &sd->base_status, sizeof(struct status_data));
mstatus->rhw.atk = mstatus->rhw.atk2 = mstatus->lhw.atk = mstatus->lhw.atk2 = mstatus->hp = mstatus->max_hp = mstatus->sp = mstatus->max_sp = 1;
mstatus->mode = 0;
memcpy(&db->vd, &sd->vd, sizeof(struct view_data));
db->base_exp = db->job_exp = db->range2 = db->range3 = 1;
db->option = 0;
md = mob->once_spawn_sub(&sd->bl, m, x, y, sd->status.name, class_, "", SZ_SMALL, AI_NONE);
if (!md)
return 0;
md->special_state.clone = 1;
mob->spawn(md);
unit->setdir(&md->bl, unit->getdir(&sd->bl));
cd = chat->create(&md->bl, market_title, "", 1, false, 0, "", 0, 1, MAX_LEVEL);
if (!cd)
return 0;
mmd = getFromMOBDATA(md,0);
CREATE(mmd, struct monster_data, 1);
mmd->market_chat_id = cd->bl.id;
safestrncpy(mmd->market_message, market_msg, CHAT_SIZE_MAX);
mmd->uid = md->bl.id;
addToMOBDATA(md, mmd, 0, true);
clif->dispchat(cd, 0);
if (sd->vd.dead_sit == 2)
clif->sitting(&md->bl);
if (market_clone_companion) {
if (sd->sc.data[SC_PUSH_CART]) {
mmd->market_pushcart = sd->sc.data[SC_PUSH_CART]->val1;
clif->sc_load(&md->bl, mmd->uid, AREA, SI_ON_PUSH_CART, mmd->market_pushcart, 0, 0);
}
if (pc_hasmount(sd) || pc_isfalcon(sd)) {
int option = sd->sc.option & (OPTION_RIDING|OPTION_DRAGON|OPTION_WUGRIDER|OPTION_FALCON|OPTION_MADOGEAR);
md->sc.option |= option;
clif->changeoption(&md->bl);
}
}
mmd->market_msg_color = msg_color;
return md->bl.id;
}
ACMD(market){
struct player_data *ssd = getFromMSD(sd,0);
char title[CHAT_SIZE_MAX], msg[CHAT_SIZE_MAX], atcmd_output[CHAT_SIZE_MAX];
int color = 0;
if (!ssd) {
CREATE(ssd, struct player_data, 1);
ssd->market_clone_id = 0;
ssd->market_clone_delay = 0;
addToMSD(sd, ssd, 0, true);
}
if (ssd->market_clone_id) {
clif->message(fd, "You already have a Market clone summoned. Type '@marketkill' to remove that clone.");
return false;
}
if (ssd->market_clone_delay + market_clone_delay > (int)time(NULL)) {
safesnprintf(atcmd_output, CHAT_SIZE_MAX, "You must wait %d seconds before using this command again.", ssd->market_clone_delay + market_clone_delay - (int)time(NULL));
clif->message(fd, atcmd_output);
return false;
}
if (!map->list[sd->bl.m].flag.town) {
clif->message(fd, "You can only use @market in a town.");
return false;
}
if (map->getcell(sd->bl.m, &sd->bl, sd->bl.x, sd->bl.y, CELL_CHKNOCHAT)) {
clif->message(fd, "You cannot use @market in this area.");
return false;
}
if (sd->status.zeny < market_clone_zenycost) {
safesnprintf(atcmd_output, CHAT_SIZE_MAX, "You must have at least %d zeny to have a Market clone.", market_clone_zenycost);
clif->message(fd, atcmd_output);
return false;
}
if (pc_isdead(sd)) {
clif->message(fd, "You can't create a Market clone while you are dead.");
return false;
}
if (sd->chat_id) {
clif->message(fd, "You can't create a Market clone while you already open a chatroom.");
return false;
}
if (sd->state.vending) {
clif->message(fd, "You can't create a Market clone while you are vending.");
return false;
}
if (sd->sc.option & OPTION_INVISIBLE) {
clif->message(fd, "You can't create a Market clone while you are using @hide.");
return false;
}
if (npc->isnear(&sd->bl)) {
clif->message(fd, "You can't create a Market clone too near to an npc.");
return false;
}
if (!*message) {
clif->message(fd, "Syntax: @market \"<Title>\" \"<Message>\" <Color>");
clif->message(fd, "The <Color> field is optional. Examples:-");
color_list(fd);
return false;
}
// if (sscanf(message, "\"%[^\"]\" \"%[^\"]\"", title, msg) < 2) {
// clif->message(fd, "Remember the Quotation Mark -> \"");
// clif->message(fd, "Syntax: @market \"<Title>\" \"<Message>\"");
// return false;
// } no more f*cking sscanf
{ // say hello to the dirties string calculation ~ Hooray ~ !!
int i = 0, j = 0;
size_t l = strlen(message) + 1;
char *temp = (char*)aMalloc(strlen(message) +1);
if (message[0] != '\"') {
clif->message(fd, "Remember the <Title> should start with a Quotation Mark -> \"");
clif->message(fd, "Syntax: @market \"<Title>\" \"<Message>\" <Color>");
aFree(temp);
return false;
}
i = 1;
while (i <= l) {
if (message[i] == '\"' || message[i] == '\0')
break;
else
temp[j++] = message[i];
++i;
}
if (message[i] != '\"') {
clif->message(fd, "Remember the <Title> should end with a Quotation Mark -> \"");
clif->message(fd, "Syntax: @market \"<Title>\" \"<Message>\" <Color>");
aFree(temp);
return false;
}
temp[j] = '\0';
safestrncpy(title, temp, CHAT_SIZE_MAX);
++i;
if (message[i] != ' ') {
clif->message(fd, "Remember the [Space] between the <Title> and <Message>.");
clif->message(fd, "Syntax: @market \"<Title>\" \"<Message>\" <Color>");
aFree(temp);
return false;
}
++i;
if (message[i] != '\"') {
clif->message(fd, "Remember the <Message> should start with a Quotation Mark -> \"");
clif->message(fd, "Syntax: @market \"<Title>\" \"<Message>\" <Color>");
aFree(temp);
return false;
}
++i;
j = 0;
while (i <= l) {
if (message[i] == '\"' || message[i] == '\0')
break;
else
temp[j++] = message[i];
++i;
}
if (message[i] != '\"') {
clif->message(fd, "Remember the <Message> should end with a Quotation Mark -> \"");
clif->message(fd, "Syntax: @market \"<Title>\" \"<Message>\" <Color>");
aFree(temp);
return false;
}
temp[j] = '\0';
safestrncpy(msg, temp, CHAT_SIZE_MAX);
++i;
if (message[i] == ' ') {
j = 0;
++i;
while (i <= l) {
if (message[i] == '\0')
break;
else
temp[j++] = message[i];
++i;
}
temp[j] = '\0';
if (strlen(temp) > 2) {
clif->message(fd, "Please input a valid number from the list.");
color_list(fd);
aFree(temp);
return false;
}
color = atoi(temp);
}
aFree(temp);
}
if (strlen(title) < 4) {
clif->message(fd, "The Title must more than 4 characters.");
return false;
}
if (strlen(title) >= CHATROOM_TITLE_SIZE) {
safesnprintf(atcmd_output, CHAT_SIZE_MAX, "The Title must not more than %d characters.", CHATROOM_TITLE_SIZE);
clif->message(fd, atcmd_output);
return false;
}
if (strlen(msg) < 4) {
clif->message(fd, "The Message must more than 4 characters.");
return false;
}
ssd->market_clone_id = mob_clone_spawn_market(sd, sd->bl.m, sd->bl.x, sd->bl.y, title, msg, color);
if (!ssd->market_clone_id) {
clif->message(fd, "Market clone Cannot be Created.");
return false;
}
if (market_clone_zenycost)
pc->payzeny(sd, market_clone_zenycost, LOG_TYPE_COMMAND, NULL);
clif->message(fd, "Market clone Created.");
return true;
}
ACMD(marketkill){
struct player_data *ssd = getFromMSD(sd,0);
if (!ssd) {
CREATE(ssd, struct player_data, 1);
ssd->market_clone_id = 0;
ssd->market_clone_delay = 0;
addToMSD(sd, ssd, 0, true);
}
if (!ssd->market_clone_id) {
clif->message(fd, "You don't have a market clone yet. Type '@market \"<title>\" \"<message>\"' to create one.");
return false;
}
status_kill(map->id2bl(ssd->market_clone_id));
clif->message(fd, "Your market clone has removed.");
ssd->market_clone_id = 0;
ssd->market_clone_delay = (int)time(NULL);
return true;
}
int npc_reload_pre(void) {
TBL_PC *sd;
struct player_data *ssd;
struct s_mapiterator *iter;
iter = mapit->alloc(MAPIT_NORMAL, BL_PC);
for (sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); sd = (TBL_PC*)mapit->next(iter)) {
if ((ssd = getFromMSD(sd,0))) {
if (ssd->market_clone_id) {
status_kill(map->id2bl(ssd->market_clone_id));
ssd->market_clone_id = 0;
ssd->market_clone_delay = (int)time(NULL);
}
}
}
mapit->free(iter);
return 0;
}
int battle_check_target_post(int retVal, struct block_list *src, struct block_list *target, int flag) {
if (retVal == 1 && target->type == BL_MOB) {
struct monster_data *mmd = getFromMOBDATA((TBL_MOB*)target, 0);
if (mmd)
return -1;
}
return retVal;
}
bool chat_joinchat_pre(struct map_session_data **sd_, int *chat_id, const char **pass) {
struct map_session_data *sd = *sd_;
struct chat_data* cd = (struct chat_data*)map->id2bl(*chat_id);
if(cd == NULL || cd->bl.type != BL_CHAT || cd->bl.m != sd->bl.m || sd->state.vending || sd->state.buyingstore || sd->chat_id || ((cd->owner->type == BL_NPC) ? cd->users+1 : cd->users) >= cd->limit) {
clif->joinchatfail(sd,0); // room full
hookStop();
return false;
}
if (cd->owner->type == BL_MOB) {
struct mob_data *md = (TBL_MOB*)cd->owner;
struct monster_data *mmd = getFromMOBDATA(md,0);
if (mmd) {
char output[CHAT_SIZE_MAX];
safesnprintf(output, CHAT_SIZE_MAX, "%s : %s", md->name, mmd->market_message);
color_message(sd->fd, mmd->market_msg_color, output);
hookStop();
return true;
}
}
return true;
}
void clif_getareachar_unit_post(struct map_session_data *sd, struct block_list *bl) {
if (bl->type == BL_MOB) {
struct monster_data *mmd = getFromMOBDATA((TBL_MOB*)bl, 0);
if (mmd) {
clif->dispchat((struct chat_data*)map->id2bl(mmd->market_chat_id), sd->fd);
if (market_clone_companion && mmd->market_pushcart)
clif->sc_load(&sd->bl, mmd->uid, SELF, SI_ON_PUSH_CART, mmd->market_pushcart, 0, 0);
}
}
return;
}
void clif_charnameack_pre(int *fd, struct block_list **bl) {
if ((*bl)->type == BL_MOB) {
TBL_MOB *md = (TBL_MOB*)(*bl);
if (md->guardian_data && md->guardian_data->g)
return;
else if (battle->bc->show_mob_info) {
struct monster_data *mmd = getFromMOBDATA(md,0);
if (!mmd)
return;
else {
char buf[103];
WBUFW(buf, 0) = 0x95;
WBUFL(buf,2) = md->bl.id;
memcpy(WBUFP(buf,6), md->name, NAME_LENGTH);
if (*fd == 0)
clif->send(buf, 30, *bl, AREA);
else {
WFIFOHEAD(*fd, 30);
memcpy(WFIFOP(*fd, 0), buf, 30);
WFIFOSET(*fd, 30);
}
hookStop();
return;
}
}
}
}
int map_quit_pre(struct map_session_data **sd) {
struct player_data *ssd = getFromMSD(*sd, 0);
if (ssd && ssd->market_clone_id)
status_kill(map->id2bl(ssd->market_clone_id));
return 0;
}
int killmonster_sub_pre(struct block_list **bl, va_list ap) {
struct mob_data *md = BL_CAST(BL_MOB, *bl);
struct monster_data *mmd = getFromMOBDATA(md, 0);
if (mmd)
hookStop();
return 0;
}
int skillnotok_pre(uint16 *skill_id, struct map_session_data **sd) {
struct player_data *ssd = getFromMSD(*sd,0);
if (ssd && ssd->market_clone_id && ((*skill_id) == MC_VENDING || (*skill_id) == ALL_BUYING_STORE)) {
clif->messagecolor_self((*sd)->fd, COLOR_RED, "You can't use vending while you already have a market clone.");
hookStop();
return 1;
}
return 0;
}
HPExport void plugin_init (void) {
addAtcommand("market", market);
addAtcommand("marketkill", marketkill);
addHookPre(npc, reload, npc_reload_pre);
addHookPost(battle, check_target, battle_check_target_post);
addHookPre(chat, join, chat_joinchat_pre);
addHookPost(clif, getareachar_unit, clif_getareachar_unit_post);
addHookPre(clif, charnameack, clif_charnameack_pre);
addHookPre(map, quit, map_quit_pre);
addHookPre(atcommand, atkillmonster_sub, killmonster_sub_pre);
addHookPre(script, buildin_killmonster_sub_strip, killmonster_sub_pre);
addHookPre(script, buildin_killmonster_sub, killmonster_sub_pre);
addHookPre(script, buildin_killmonsterall_sub_strip, killmonster_sub_pre);
addHookPre(script, buildin_killmonsterall_sub, killmonster_sub_pre);
addHookPre(skill, not_ok, skillnotok_pre);
}
HPExport void server_online (void) {
ShowInfo ("'%s' Plugin by Dastgir/Hercules. Version '%s'\n",pinfo.name,pinfo.version);
}
storageadditem
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "common/HPMi.h"
#include "map/intif.h"
#include "map/pc.h"
#include "map/storage.h"
#include "common/HPMDataCheck.h" // should always be the last file included! (if you don't make it last, it'll intentionally break compile time)
HPExport struct hplugin_info pinfo = {
"storageadditem", // Plugin name
SERVER_TYPE_MAP,// Which server types this plugin works with?
"0.1", // Plugin version
HPM_VERSION, // HPM Version (don't change, macro is automatically updated)
};
/*==========================================
* storageadditem <item id>,<amount>{,<account id>}
* Adds items from the target/attached player.
*==========================================*/
BUILDIN(storageadditem) {
TBL_PC *sd;
struct item it;
if (script_hasdata(st,4)) {
int account_id = script_getnum(st,4);
sd = map->id2sd(account_id); // <account id>
if (sd == NULL) {
ShowError("script:storageadditem: player not found (AID=%d).\n", account_id);
st->state = END;
return false;
}
} else {
sd = script->rid2sd(st);// attached player
if (sd == NULL)
return true;
}
memset(&it, 0, sizeof(it));
if (script_isstringtype(st, 2)) {
const char* item_name = script_getstr(st, 2);
struct item_data* id = itemdb->search_name(item_name);
if (id == NULL) {
ShowError("script:storageadditem: unknown item \"%s\".\n", item_name);
st->state = END;
return false;
}
it.nameid = id->nameid;// "<item name>"
} else {
it.nameid = script_getnum(st, 2);// <item id>
if (!itemdb->exists(it.nameid)) {
ShowError("script:storageadditem: unknown item \"%d\".\n", it.nameid);
st->state = END;
return false;
}
}
it.amount=script_getnum(st,3);
if( it.amount <= 0 ) {
return true;// nothing to do
}
if( sd->status.storage.storage_amount > MAX_STORAGE ) {
return 0; // storage full
}
it.identify=1;
storage->open(sd);
storage->additem(sd,&it,it.amount);
storage->close(sd);
}
/* Server Startup */
HPExport void plugin_init (void) {
addScriptCommand( "storageadditem", "vi?", storageadditem);
}
Errors and Warnings
Severity Code Description Project File Line Suppression State
Warning C4018 '<=': signed/unsigned mismatch char-server hercules\src\char\int_party.c 320
Warning C4013 'GET_SYMBOL' undefined; assuming extern returning int autopots Hercules\src\plugins\autopots.c 267
Warning C4047 '=': 'clif_interface *' differs in levels of indirection from 'int' autopots Hercules\src\plugins\autopots.c 267
Warning C4047 '=': 'script_interface *' differs in levels of indirection from 'int' autopots Hercules\src\plugins\autopots.c 268
Warning C4047 '=': 'pc_interface *' differs in levels of indirection from 'int' autopots Hercules\src\plugins\autopots.c 269
Warning C4047 '=': 'atcommand_interface *' differs in levels of indirection from 'int' autopots Hercules\src\plugins\autopots.c 270
Warning C4047 '=': 'map_interface *' differs in levels of indirection from 'int' autopots Hercules\src\plugins\autopots.c 271
Warning C4047 '=': 'unit_interface *' differs in levels of indirection from 'int' autopots Hercules\src\plugins\autopots.c 272
Warning C4047 '=': 'timer_interface *' differs in levels of indirection from 'int' autopots Hercules\src\plugins\autopots.c 273
Warning C4047 '=': 'itemdb_interface *' differs in levels of indirection from 'int' autopots Hercules\src\plugins\autopots.c 274
Warning C4013 'hookStop' undefined; assuming extern returning int maintenance Hercules\src\plugins\maintenance.c 205
Warning C4013 'addHookPre' undefined; assuming extern returning int maintenance Hercules\src\plugins\maintenance.c 550
Warning C4018 '<=': signed/unsigned mismatch market Hercules\src\plugins\market.c 259
Warning C4018 '<=': signed/unsigned mismatch market Hercules\src\plugins\market.c 290
Warning C4018 '<=': signed/unsigned mismatch market Hercules\src\plugins\market.c 309
Warning C4013 'hookStop' undefined; assuming extern returning int noitem Hercules\src\plugins\noitem.c 107
Warning C4013 'addHookPre' undefined; assuming extern returning int noitem Hercules\src\plugins\noitem.c 190
Warning C4013 'addHookPost' undefined; assuming extern returning int noitem Hercules\src\plugins\noitem.c 192
Error LNK2019 unresolved external symbol _GET_SYMBOL referenced in function _plugin_init autopots Hercules\vcproj-14\autopots.obj 1
Error MSB6006 "link.exe" exited with code 1120. maintenance C:\Program Files\MSBuild\Microsoft.Cpp\v4.0\V140\Microsoft.CppCommon.targets 638
Error MSB6006 "link.exe" exited with code 1120. autopots C:\Program Files\MSBuild\Microsoft.Cpp\v4.0\V140\Microsoft.CppCommon.targets 638
Error MSB6006 "link.exe" exited with code 1120. noitem C:\Program Files\MSBuild\Microsoft.Cpp\v4.0\V140\Microsoft.CppCommon.targets 638
Error LNK2019 unresolved external symbol _hookStop referenced in function _pc_authok_pre maintenance Hercules\vcproj-14\maintenance.obj 1
Error LNK1120 1 unresolved externals autopots Hercules\plugins\autopots.dll 1
Error LNK2019 unresolved external symbol _hookStop referenced in function _npc_parse_unknown_mapflag_pre noitem Hercules\vcproj-14\noitem.obj 1
Error LNK2019 unresolved external symbol _addHookPre referenced in function _plugin_init maintenance Hercules\vcproj-14\maintenance.obj 1
Error LNK2019 unresolved external symbol _addHookPre referenced in function _plugin_init noitem Hercules\vcproj-14\noitem.obj 1
Error LNK1120 2 unresolved externals maintenance Hercules\plugins\maintenance.dll 1
Error LNK2019 unresolved external symbol _addHookPost referenced in function _plugin_init noitem Hercules\vcproj-14\noitem.obj 1
Error LNK1120 3 unresolved externals noitem Hercules\plugins\noitem.dll 1
Warning C4715 'buildin_storageadditem': not all control paths return a value storageadditem hercules\src\plugins\storageadditem.c 72
Error C1083 Cannot open include file: 'common/malloc.h': No such file or directory partyscript Hercules\src\plugins\partyscript.c 13
autopots.c
maintenance.c
partyscript.c
noitem.c
market.c
storageadditem
Errors and Warnings
Share this post
Link to post
Share on other sites