Initial release of VIP System.

By default system is disabled (src/config/core.h).
This follows the iRO implementation VIP System. More information can be found on the iRO Wiki.
All settings also have individual configs.
Official VIP scripts will be implemented later.
Big thanks to lighta and Cydh for support and debugging.
This commit is contained in:
aleos89 2013-11-18 15:19:52 -05:00
parent 24ca5b5c3c
commit 30648216ec
40 changed files with 944 additions and 241 deletions

View File

@ -5,6 +5,8 @@
//--------------------------------------------------------------
// Note 1: Value is a config switch (on/off, yes/no or 1/0)
// Note 2: Value is in percents (100 means 100%)
// Note 3: Value is a bit field. If no description is given,
// assume unit types (1: Pc, 2: Mob, 4: Pet, 8: Homun)
//--------------------------------------------------------------
// Players' maximum HP rate? (Default is 100)
@ -141,4 +143,48 @@ idle_no_autoloot: 0
// Minimum distance a vending/chat room must be from a NPC in order to be placed.
// Default: 3 (0: disabled).
min_npc_vendchat_distance: 3
min_npc_vendchat_distance: 3
// Storage slot increase. Setting to 0 will disable.
// Give more storage slots above the MIN_STORAGE limit.
// Note: MIN_STORAGE + storage_increase cannot exceed MAX_STORAGE.
// Default: 300
vip_storage_increase: 300
// Base experience rate increase. Setting to 0 will disable. (Note 2)
// Default: 50
vip_base_exp_increase: 50
// Experience penalty rate multiplier for Non-VIP accounts
// Multiplies the 'death_penalty_base' and 'death_penalty_job' settings in 'conf/battle/exp.conf'.
// Default: 3 (3*100 = 3% penalty)
vip_exp_penalty_base_normal: 3
vip_exp_penalty_job_normal: 3
// Experience penalty rate multiplier for VIP accounts
// Multiplies the 'death_penalty_base' and 'death_penalty_job' settings in 'conf/battle/exp.conf'.
// Default: 1 (1*100 = 1% penalty)
vip_exp_penalty_base: 1
vip_exp_penalty_job: 1
// Job experience rate increase. Setting to 0 will disable. (Note 2)
// Default: 50
vip_job_exp_increase: 50
// Battle Manual experience increase. Setting to 0 will disable.
// - Regular/Thick Battle Manual: 50+(50/X) = 75%
// - HE Battle Manual: 100+(100/X) = 150%
// - Battle Manual x3: 200+(200/X) = 300%
// Note: X is what the config is set to.
// Default: 2
vip_bm_increase: 2
// Item drop increase. Setting to 0 will disable.
// Note: 50 = 0.5%
// Default: 50
vip_drop_increase: 50
// GemStone requirement. Setting to false will disable.
// Can the VIP Group ignore GemStone requirement for skills?
// Default: true
vip_gemstone: true

View File

@ -140,11 +140,6 @@ char_name_option: 1
// Note: Don't add spaces unless you mean to add 'space' to the list.
char_name_letters: abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890
// How many Characters are allowed per Account ? (0 = disabled)
// You can not exceed the limit of MAX_CHARS slots, defined in mmo.h
// Doing that, chars_per_account will be default to MAX_CHARS.
chars_per_account: 0
// Restrict character deletion by BaseLevel
// 0: no restriction (players can delete characters of any level)
// -X: you can't delete chars with BaseLevel <= X

View File

@ -219,6 +219,19 @@ groups: (
any_warp: true
}
},
{
id: 5
name: "VIP"
inherit: ( "Player" ) /* can do everything Players can */
level: 0
commands: {
rates: true
who: true
}
permissions: {
/* no permissions by default */
}
},
{
id: 10
name: "Law Enforcement"

View File

@ -73,6 +73,23 @@ group_id_to_connect: -1
// 0 or more: group id
min_group_id_to_connect: -1
// Which group (ID) will be denoted as the VIP Group?
// Default: 5
vip_group: 5
// How many Characters are allowed per Account ? (0 = disabled)
// You can not exceed the limit of MAX_CHARS slots, defined in mmo.h
// Doing that, chars_per_account will be default to MAX_CHARS.
// If setting to 0 MIN_CHARS value will be used.
chars_per_account: 0
// Max character limit increase. Setting to 0 will disable.
// Increase MAX_CHAR if you want to increase char_increase.
// Note: MAX_CHARS - chars_per_account = Amount of VIP Chars (char_increase value in login table).
// Note2: this setting need to be set after chars_per_account
// Default: 6
vip_char_increase: 6
// Starting additional sec from now for the limited time at creation of account
// -1: new account are created with UNlimited time (default value)
// 0 or more: new accounts was created by addition of the value (in sec) to the actual time (to set first limited time)

View File

@ -693,6 +693,16 @@
694: Hanbok
695: Rebellion
// @vip
700: Usage: @vip <time> <character name>
701: Invalid time for VIP command.
702: Time parameter format is +/-<value> to alter. y/a = Year, m = Month, d/j = Day, h = Hour, n/mn = Minute, s = Second.
703: GM has removed your VIP time.
704: Player is no longer VIP.
705: %s is VIP for %d years, %d months, %d days, %d hours and %d minutes.
706: This player is now VIP for %d years, %d months, %d days, %d hours and %d minutes.
707: You are VIP until
//708-899 free
//------------------------------------
// More atcommands message

View File

@ -1761,6 +1761,7 @@ packet_ver: 30
0x0977,14 //Monster HP Bar
0x0916,26,guildinvite2,2
0x091d,18,bookingregreq,2:4:6
//0x08cb,10,ZC_PERSONAL_INFOMATION,2:4:6:8:10:11:13:15 // Disabled until further information is found.
//2012-04-18aRagexeRE [Special Thanks to Judas!]
packet_ver:31
@ -1855,6 +1856,8 @@ packet_ver: 34
0x0977,14 //Monster HP Bar
0x0978,6,reqworldinfo,2
0x0979,50 //ackworldinfo
//0x097b,16,ZC_PERSONAL_INFOMATION,2:4:8:12:16:17:21:25 // Disabled until further information is found.
//0x0981,12,ZC_PERSONAL_INFOMATION_CHN,2:4:6:8:12:13:15:17:10 // Disabled until further information is found.
0x0990,31 //additem
0x0991,-1 //inv itemlist normal
0x0992,-1 //inv itemlist equip

View File

@ -460,6 +460,8 @@ CREATE TABLE IF NOT EXISTS `login` (
`pincode` varchar(4) NOT NULL DEFAULT '',
`pincode_change` int(11) unsigned NOT NULL DEFAULT '0',
`bank_vault` int(11) NOT NULL DEFAULT '0',
`vip_time` int(11) unsigned NOT NULL default '0',
`old_group` tinyint(3) NOT NULL default '0',
PRIMARY KEY (`account_id`),
KEY `name` (`userid`)
) ENGINE=MyISAM AUTO_INCREMENT=2000000;

View File

@ -111,7 +111,6 @@ char unknown_char_name[NAME_LENGTH] = "Unknown"; // Name to use when the request
#define TRIM_CHARS "\255\xA0\032\t\x0A\x0D " //The following characters are trimmed regardless because they cause confusion and problems on the servers. [Skotlex]
char char_name_letters[1024] = ""; // list of letters/symbols allowed (or not) in a character name. by [Yor]
int char_per_account = 0; //Maximum chars per account (default unlimited) [Sirius]
int char_del_level = 0; //From which level u can delete character [Lupus]
int char_del_delay = 86400;
@ -133,7 +132,9 @@ struct char_session_data {
char email[40]; // e-mail (default: a@a.com) by [Yor]
time_t expiration_time; // # of seconds 1/1/1970 (timestamp): Validity limit of the account (0 = unlimited)
int group_id; // permission
uint8 char_slots;
uint8 char_slots; // total number of characters that can be created
uint8 chars_vip;
uint8 chars_billing;
uint32 version;
uint8 clienttype;
char new_name[NAME_LENGTH];
@ -146,6 +147,7 @@ struct char_session_data {
// Addon system
int bank_vault;
unsigned int char_moves[MAX_CHARS]; // character moves left
uint8 isvip;
};
struct startitem {
@ -183,6 +185,11 @@ void pincode_notifyLoginPinError( int account_id );
void pincode_decrypt( uint32 userSeed, char* pin );
int pincode_compare( int fd, struct char_session_data* sd, char* pin );
int mapif_parse_vipactive(int fd);
int mapif_vipack(uint32 aid, uint32 vip_time, uint8 isvip, uint32 groupid);
int logif_reqviddata(uint32 aid, uint8 type, uint32 add_vip_time);
int logif_parse_vipack(int fd);
// Addon system
bool char_move_enabled = true;
bool char_movetoused = true;
@ -1441,8 +1448,6 @@ int mmo_char_sql_init(void)
{
char_db_= idb_alloc(DB_OPT_RELEASE_DATA);
ShowStatus("Characters per Account: '%d'.\n", char_per_account);
//the 'set offline' part is now in check_login_conn ...
//if the server connects to loginserver
//it will dc all off players
@ -1581,9 +1586,9 @@ int make_new_char_sql(struct char_session_data* sd, char* name_, int str, int ag
//check other inputs
#if PACKETVER >= 20120307
if(slot >= sd->char_slots)
if(slot < 0 || slot >= sd->char_slots)
#else
if((slot >= sd->char_slots) // slots
if((slot < 0 || slot >= sd->char_slots) // slots
|| (str + agi + vit + int_ + dex + luk != 6*5 ) // stats
|| (str < 1 || str > 9 || agi < 1 || agi > 9 || vit < 1 || vit > 9 || int_ < 1 || int_ > 9 || dex < 1 || dex > 9 || luk < 1 || luk > 9) // individual stat values
|| (str + int_ != 10 || agi + luk != 10 || vit + dex != 10) ) // pairs
@ -1596,12 +1601,10 @@ int make_new_char_sql(struct char_session_data* sd, char* name_, int str, int ag
// check the number of already existing chars in this account
if( char_per_account != 0 ) {
if( SQL_ERROR == Sql_Query(sql_handle, "SELECT 1 FROM `%s` WHERE `account_id` = '%d'", char_db, sd->account_id) )
Sql_ShowDebug(sql_handle);
if( Sql_NumRows(sql_handle) >= char_per_account )
return -2; // character account limit exceeded
}
if( SQL_ERROR == Sql_Query(sql_handle, "SELECT 1 FROM `%s` WHERE `account_id` = '%d'", char_db, sd->account_id) )
Sql_ShowDebug(sql_handle);
if( Sql_NumRows(sql_handle) >= sd->char_slots )
return -2; // character account limit exceeded
// check char slot
if( SQL_ERROR == Sql_Query(sql_handle, "SELECT 1 FROM `%s` WHERE `account_id` = '%d' AND `char_num` = '%d' LIMIT 1", char_db, sd->account_id, slot) )
@ -1979,7 +1982,7 @@ void char_parse_req_charlist(int fd, struct char_session_data* sd){
//----------------------------------------
int mmo_char_send006b(int fd, struct char_session_data* sd){
int j, offset = 0;
bool newvers = (sd->version >= (uint32)date2version(20100413));
bool newvers = (sd->version >= date2version(20100413));
if(newvers) //20100413
offset += 3;
if (save_log)
@ -1989,11 +1992,16 @@ int mmo_char_send006b(int fd, struct char_session_data* sd){
WFIFOHEAD(fd,j + MAX_CHARS*MAX_CHAR_BUF);
WFIFOW(fd,0) = 0x6b;
if(newvers){ //20100413
WFIFOB(fd,4) = MAX_CHARS; // Max slots.
WFIFOB(fd,5) = sd->char_slots; // Available slots. (PremiumStartSlot)
WFIFOB(fd,6) = MAX_CHARS; // Premium slots. (Any existent chars past sd->char_slots but within MAX_CHARS will show a 'Premium Service' in red)
WFIFOB(fd,4) = MAX_CHARS; // Max slots
WFIFOB(fd,5) = MAX_CHARS - sd->chars_billing - sd->chars_vip; // PremiumStartSlot
WFIFOB(fd,6) = MAX_CHARS - sd->chars_billing; // PremiumEndSlot
/* this+0x7 char dummy1_beginbilling */
/* this+0x8 unsigned long code */
/* this+0xc unsigned long time1 */
/* this+0x10 unsigned long time2 */
/* this+0x14 char dummy2_endbilling[7] */
}
memset(WFIFOP(fd,4 + offset), 0, 20); // unknown bytes
memset(WFIFOP(fd,4 + offset), 0, 20); // unknown bytes 4-24 7-27
j+=mmo_chars_fromsql(sd, WFIFOP(fd,j));
WFIFOW(fd,2) = j; // packet len
WFIFOSET(fd,j);
@ -2010,18 +2018,18 @@ void mmo_char_send082d(int fd, struct char_session_data* sd) {
WFIFOHEAD(fd,29);
WFIFOW(fd,0) = 0x82d;
WFIFOW(fd,2) = 29;
WFIFOB(fd,4) = sd->char_slots;
WFIFOB(fd,5) = MAX_CHARS - sd->char_slots;
WFIFOB(fd,6) = MAX_CHARS - sd->char_slots;
WFIFOB(fd,7) = sd->char_slots;
WFIFOB(fd,8) = sd->char_slots;
WFIFOB(fd,4) = MAX_CHARS - sd->chars_billing - sd->chars_vip; //NormalSlotNum
WFIFOB(fd,5) = sd->chars_vip; //PremiumSlotNum
WFIFOB(fd,6) = sd->chars_billing; //BillingSlotNum
WFIFOB(fd,7) = sd->char_slots; //ProducibleSlotNum
WFIFOB(fd,8) = sd->char_slots; //ValidSlotNum
memset(WFIFOP(fd,9), 0, 20); // unused bytes
WFIFOSET(fd,29);
}
void mmo_char_send(int fd, struct char_session_data* sd){
//ShowInfo("sd->version = %d\n",sd->version);
if(sd->version > (uint32)date2version(20130000) ){
if(sd->version > date2version(20130000) ){
mmo_char_send082d(fd,sd);
char_charlist_notify(fd,sd);
char_block_character(fd,sd);
@ -2170,7 +2178,7 @@ int loginif_BankingReq(int32 account_id, int8 type, int32 data){
WFIFOB(login_fd,6) = type;
WFIFOL(login_fd,7) = data;
WFIFOSET(login_fd,11);
return 1;
return 1;
}
return 0;
}
@ -2239,6 +2247,76 @@ int mapif_parse_ReqBankInfo(int fd){
return 1;
}
/*
* ZH 0x2b2c
* HA 0x2742
* We received a request vip_info from map-server.
* Transmit it to login-serv as it's the one knowing the info
*/
int mapif_parse_vipactive(int fd) {
#ifdef VIP_ENABLE
uint32 aid = RFIFOL(fd,2); //aid
uint8 type = RFIFOB(fd,6); //type
uint32 adddur = RFIFOL(fd,7); //req_inc_duration
RFIFOSKIP(fd,11);
logif_reqviddata(aid, type, adddur);
#endif
return 0;
}
/*
* HZ 0x2b2b
* Transmist vip data to mapserv
*/
int mapif_vipack(uint32 aid, uint32 vip_time, uint8 isvip, uint32 groupid) {
#ifdef VIP_ENABLE
uint8 buf[16];
WBUFW(buf,0) = 0x2b2b;
WBUFL(buf,2) = aid;
WBUFL(buf,6) = vip_time;
WBUFB(buf,10) = isvip;
WBUFL(buf,11) = groupid;
mapif_sendall(buf,15); // inform all map-servers attached.
#endif
return 0;
}
/*
* HZ 0x2b2b
* Request vip data from loginserv
*/
int logif_reqviddata(uint32 aid, uint8 type, uint32 add_vip_time) {
#ifdef VIP_ENABLE
WFIFOHEAD(login_fd,11);
WFIFOW(login_fd,0) = 0x2742;
WFIFOL(login_fd,2) = aid; //aid
WFIFOB(login_fd,6) = type; //type
WFIFOL(login_fd,7) = add_vip_time; //req_inc_duration
WFIFOSET(login_fd,11);
#endif
return 0;
}
/*
* AH 0x2743
* We received the info from login-serv, transmit it to map
*/
int logif_parse_vipack(int fd) {
#ifdef VIP_ENABLE
if (RFIFOREST(fd) < 15)
return 0;
else {
uint32 aid = RFIFOL(fd,2); //aid
uint32 vip_time = RFIFOL(fd,6); //vip_time
uint8 isvip = RFIFOB(fd,10); //isvip
uint32 groupid = RFIFOL(fd,11); //new group id
RFIFOSKIP(fd,15);
mapif_vipack(aid,vip_time,isvip,groupid);
}
#endif
return 1;
}
/// Resets all the data.
void loginif_reset(void)
@ -2288,31 +2366,30 @@ void loginif_on_ready(void)
int logif_parse_reqpincode(int fd, struct char_session_data *sd){
#if PACKETVER >= 20110309
if( pincode_enabled ){
// PIN code system enabled
if( strlen( sd->pincode ) <= 0 ){
// No PIN code has been set yet
if( pincode_force ) pincode_sendstate( fd, sd, PINCODE_NEW );
else pincode_sendstate( fd, sd, PINCODE_PASSED );
} else {
if( !pincode_changetime || ( sd->pincode_change + pincode_changetime ) > time(NULL) ){
struct online_char_data* node = (struct online_char_data*)idb_get( online_char_db, sd->account_id );
if( node != NULL && node->pincode_success ){ // User has already passed the check
pincode_sendstate( fd, sd, PINCODE_PASSED );
}else{
// Ask user for his PIN code
pincode_sendstate( fd, sd, PINCODE_ASK );
}
}else{ // User hasnt changed his PIN code too long
pincode_sendstate( fd, sd, PINCODE_EXPIRED );
}
}
} else { // PIN code system disabled
pincode_sendstate( fd, sd, PINCODE_OK );
}
if( pincode_enabled ){
// PIN code system enabled
if( strlen( sd->pincode ) <= 0 ){
// No PIN code has been set yet
if( pincode_force ) pincode_sendstate( fd, sd, PINCODE_NEW );
else pincode_sendstate( fd, sd, PINCODE_PASSED );
} else {
if( !pincode_changetime || ( sd->pincode_change + pincode_changetime ) > time(NULL) ){
struct online_char_data* node = (struct online_char_data*)idb_get( online_char_db, sd->account_id );
if( node != NULL && node->pincode_success ){ // User has already passed the check
pincode_sendstate( fd, sd, PINCODE_PASSED );
}else{
// Ask user for his PIN code
pincode_sendstate( fd, sd, PINCODE_ASK );
}
}else{ // User hasnt changed his PIN code too long
pincode_sendstate( fd, sd, PINCODE_EXPIRED );
}
}
} else { // PIN code system disabled
pincode_sendstate( fd, sd, PINCODE_OK );
}
#endif
return 0;
return 0;
}
int parse_fromlogin(int fd) {
@ -2352,6 +2429,7 @@ int parse_fromlogin(int fd) {
switch( command )
{
case 0x2741: loginif_parse_BankingAck(fd); break;
case 0x2743: logif_parse_vipack(fd); break;
// acknowledgement of connect-to-loginserver request
case 0x2711:
@ -2415,7 +2493,7 @@ int parse_fromlogin(int fd) {
break;
case 0x2717: // account data
if (RFIFOREST(fd) < 76)
if (RFIFOREST(fd) < 79)
return 0;
// find the authenticated session with this account id
@ -2431,11 +2509,14 @@ int parse_fromlogin(int fd) {
ShowError("Account '%d' `character_slots` column is higher than supported MAX_CHARS (%d), update MAX_CHARS in mmo.h! capping to MAX_CHARS...\n",sd->account_id,sd->char_slots);
sd->char_slots = MAX_CHARS;/* cap to maximum */
} else if ( !sd->char_slots )/* no value aka 0 in sql */
sd->char_slots = MAX_CHARS;/* cap to maximum */
sd->char_slots = MIN_CHARS;/* cap to minimum */
safestrncpy(sd->birthdate, (const char*)RFIFOP(fd,52), sizeof(sd->birthdate));
safestrncpy(sd->pincode, (const char*)RFIFOP(fd,63), sizeof(sd->pincode));
sd->pincode_change = (time_t)RFIFOL(fd,68);
sd->bank_vault = RFIFOL(fd,72);
sd->isvip = RFIFOB(fd,76);
sd->chars_vip = RFIFOB(fd,77);
sd->chars_billing = RFIFOB(fd,78);
ARR_FIND( 0, ARRAYLENGTH(server), server_id, server[server_id].fd > 0 && server[server_id].map[0] );
// continued from char_auth_ok...
if( server_id == ARRAYLENGTH(server) || //server not online, bugreport:2359
@ -2452,7 +2533,7 @@ int parse_fromlogin(int fd) {
logif_parse_reqpincode(i, sd);
}
}
RFIFOSKIP(fd,76);
RFIFOSKIP(fd,79);
break;
// login-server alive packet
@ -3680,7 +3761,7 @@ int parse_frommap(int fd)
case 0x2b28: mapif_parse_UpdBankInfo(fd); break;
case 0x2b2a: mapif_parse_ReqBankInfo(fd); break;
case 0x2b2c: mapif_parse_vipactive(fd); break;
case 0x2b2d: //Load data
if (RFIFOREST(fd) < 6)
return 0;
@ -5382,13 +5463,6 @@ int char_config_read(const char* cfgName)
char_name_option = atoi(w2);
} else if (strcmpi(w1, "char_name_letters") == 0) {
safestrncpy(char_name_letters, w2, sizeof(char_name_letters));
} else if (strcmpi(w1, "chars_per_account") == 0) { //maxchars per account [Sirius]
char_per_account = atoi(w2);
if( char_per_account == 0 || char_per_account > MAX_CHARS ) {
if( char_per_account > MAX_CHARS )
ShowWarning("Max chars per account '%d' exceeded limit. Defaulting to '%d'.\n", char_per_account, MAX_CHARS);
char_per_account = MAX_CHARS;
}
} else if (strcmpi(w1, "char_del_level") == 0) { //disable/enable char deletion by its level condition [Lupus]
char_del_level = atoi(w2);
} else if (strcmpi(w1, "char_del_delay") == 0) {

View File

@ -71,7 +71,8 @@
#define MAX_MAP_PER_SERVER 1500 // Increased to allow creation of Instance Maps
#define MAX_INVENTORY 100
//Max number of characters per account. Note that changing this setting alone is not enough if the client is not hexed to support more characters as well.
#define MAX_CHARS 9
//Max value tested was 265
#define MAX_CHARS 9
//Number of slots carded equipment can have. Never set to less than 4 as they are also used to keep the data of forged items/equipment. [Skotlex]
//Note: The client seems unable to receive data for more than 4 slots due to all related packets having a fixed size.
#define MAX_SLOTS 4
@ -90,7 +91,7 @@
#define DEFAULT_WALK_SPEED 150
#define MIN_WALK_SPEED 0
#define MAX_WALK_SPEED 1000
#define MAX_STORAGE 600
#define MAX_STORAGE 600 /// Max number of storage slots the client can support. Used as a cap for the VIP System.
#define MAX_GUILD_STORAGE 600
#define MAX_PARTY 12
#define MAX_GUILD 16+10*6 // increased max guild members +6 per 1 extension levels [Lupus]

View File

@ -259,7 +259,7 @@ uint32 MakeDWord(uint16 word0, uint16 word1)
( (uint32)(word1 << 0x10) );
}
int date2version(int date){
uint32 date2version(int date){
if(date < 20040906) return 5;
else if(date < 20040920) return 10;
else if(date < 20041005) return 11;

View File

@ -29,6 +29,6 @@ extern uint16 GetWord(uint32 val, int idx);
extern uint16 MakeWord(uint8 byte0, uint8 byte1);
extern uint32 MakeDWord(uint16 word0, uint16 word1);
int date2version(int date);
uint32 date2version(int date);
#endif /* _UTILS_H_ */

View File

@ -72,6 +72,24 @@
/// Comment to disable the job HP/SP tables and use formulas instead
#define HP_SP_TABLES
/// Uncomment to enable VIP system.
//#define VIP_ENABLE
#ifdef VIP_ENABLE
#define MIN_STORAGE 300 // Default number of storage slots.
#define MIN_CHARS 3 // Default number of characters per account.
#define MAX_CHAR_VIP 6 // This must be less than MAX_CHARS
#define MAX_CHAR_BILLING 0 // This must be less than MAX_CHARS
#else
#define MIN_STORAGE 600 // If the VIP system is disabled the min = max.
#define MIN_CHARS 9 // Default number of characters per account.
#define MAX_CHAR_BILLING 0
#define MAX_CHAR_VIP 0
#endif
#if (MIN_CHARS + MAX_CHAR_VIP + MAX_CHAR_BILLING) > MAX_CHARS
#error "Config of MAX_CHARS is invalid"
#endif
#define VIP_SCRIPT 0 //enable or disable scripts (require vip_enable)
/**
* No settings past this point
**/

View File

@ -34,8 +34,7 @@ AccountDB* ACCOUNTDB_CONSTRUCTOR(ACCOUNTDB_ENGINE_4)(void);
#endif
struct mmo_account
{
struct mmo_account {
int account_id;
char userid[NAME_LENGTH];
char pass[32+1]; // 23+1 for plaintext, 32+1 for md5-ed passwords
@ -54,6 +53,10 @@ struct mmo_account
time_t pincode_change; // (timestamp): last time of pincode change
int account_reg2_num;
int bank_vault;
#ifdef VIP_ENABLE
int old_group;
int vip_time;
#endif
struct global_reg account_reg2[ACCOUNT_REG2_NUM]; // account script variables (stored on login server)
};

View File

@ -7,6 +7,7 @@
#include "../common/sql.h"
#include "../common/strlib.h"
#include "../common/timer.h"
#include "../config/core.h"
#include "account.h"
#include <stdlib.h>
#include <string.h>
@ -522,7 +523,11 @@ static bool mmo_auth_fromsql(AccountDB_SQL* db, struct mmo_account* acc, int acc
// retrieve login entry for the specified account
if( SQL_ERROR == Sql_Query(sql_handle,
"SELECT `account_id`,`userid`,`user_pass`,`sex`,`email`,`group_id`,`state`,`unban_time`,`expiration_time`,`logincount`,`lastlogin`,`last_ip`,`birthdate`,`character_slots`,`pincode`, `pincode_change`, `bank_vault` FROM `%s` WHERE `account_id` = %d",
#ifdef VIP_ENABLE
"SELECT `account_id`,`userid`,`user_pass`,`sex`,`email`,`group_id`,`state`,`unban_time`,`expiration_time`,`logincount`,`lastlogin`,`last_ip`,`birthdate`,`character_slots`,`pincode`, `pincode_change`, `bank_vault`, `vip_time`, `old_group` FROM `%s` WHERE `account_id` = %d",
#else
"SELECT `account_id`,`userid`,`user_pass`,`sex`,`email`,`group_id`,`state`,`unban_time`,`expiration_time`,`logincount`,`lastlogin`,`last_ip`,`birthdate`,`character_slots`,`pincode`, `pincode_change`, `bank_vault` FROM `%s` WHERE `account_id` = %d",
#endif
db->account_db, account_id )
) {
Sql_ShowDebug(sql_handle);
@ -552,10 +557,12 @@ static bool mmo_auth_fromsql(AccountDB_SQL* db, struct mmo_account* acc, int acc
Sql_GetData(sql_handle, 14, &data, NULL); safestrncpy(acc->pincode, data, sizeof(acc->pincode));
Sql_GetData(sql_handle, 15, &data, NULL); acc->pincode_change = atol(data);
Sql_GetData(sql_handle, 16, &data, NULL); acc->bank_vault = atoi(data);
#ifdef VIP_ENABLE
Sql_GetData(sql_handle, 17, &data, NULL); acc->vip_time = atol(data);
Sql_GetData(sql_handle, 18, &data, NULL); acc->old_group = atoi(data);
#endif
Sql_FreeResult(sql_handle);
// retrieve account regs for the specified user
if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `str`,`value` FROM `%s` WHERE `type`='1' AND `account_id`='%d'", db->accreg_db, acc->account_id) )
{
@ -600,7 +607,11 @@ static bool mmo_auth_tosql(AccountDB_SQL* db, const struct mmo_account* acc, boo
if( is_new )
{// insert into account table
if( SQL_SUCCESS != SqlStmt_Prepare(stmt,
#ifdef VIP_ENABLE
"INSERT INTO `%s` (`account_id`, `userid`, `user_pass`, `sex`, `email`, `group_id`, `state`, `unban_time`, `expiration_time`, `logincount`, `lastlogin`, `last_ip`, `birthdate`, `character_slots`, `pincode`, `pincode_change`, `bank_vault`, `vip_time`, `old_group` ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
#else
"INSERT INTO `%s` (`account_id`, `userid`, `user_pass`, `sex`, `email`, `group_id`, `state`, `unban_time`, `expiration_time`, `logincount`, `lastlogin`, `last_ip`, `birthdate`, `character_slots`, `pincode`, `pincode_change`, `bank_vault`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
#endif
db->account_db)
|| SQL_SUCCESS != SqlStmt_BindParam(stmt, 0, SQLDT_INT, (void*)&acc->account_id, sizeof(acc->account_id))
|| SQL_SUCCESS != SqlStmt_BindParam(stmt, 1, SQLDT_STRING, (void*)acc->userid, strlen(acc->userid))
@ -619,6 +630,10 @@ static bool mmo_auth_tosql(AccountDB_SQL* db, const struct mmo_account* acc, boo
|| SQL_SUCCESS != SqlStmt_BindParam(stmt, 14, SQLDT_STRING, (void*)&acc->pincode, strlen(acc->pincode))
|| SQL_SUCCESS != SqlStmt_BindParam(stmt, 15, SQLDT_LONG, (void*)&acc->pincode_change, sizeof(acc->pincode_change))
|| SQL_SUCCESS != SqlStmt_BindParam(stmt, 16, SQLDT_INT, (void*)&acc->bank_vault, sizeof(acc->bank_vault))
#ifdef VIP_ENABLE
|| SQL_SUCCESS != SqlStmt_BindParam(stmt, 17, SQLDT_LONG, (void*)&acc->vip_time, sizeof(acc->vip_time))
|| SQL_SUCCESS != SqlStmt_BindParam(stmt, 18, SQLDT_INT, (void*)&acc->old_group, sizeof(acc->old_group))
#endif
|| SQL_SUCCESS != SqlStmt_Execute(stmt)
) {
SqlStmt_ShowDebug(stmt);
@ -627,7 +642,13 @@ static bool mmo_auth_tosql(AccountDB_SQL* db, const struct mmo_account* acc, boo
}
else
{// update account table
if( SQL_SUCCESS != SqlStmt_Prepare(stmt, "UPDATE `%s` SET `userid`=?,`user_pass`=?,`sex`=?,`email`=?,`group_id`=?,`state`=?,`unban_time`=?,`expiration_time`=?,`logincount`=?,`lastlogin`=?,`last_ip`=?,`birthdate`=?,`character_slots`=?,`pincode`=?, `pincode_change`=?, `bank_vault`=? WHERE `account_id` = '%d'", db->account_db, acc->account_id)
if( SQL_SUCCESS != SqlStmt_Prepare(stmt,
#ifdef VIP_ENABLE
"UPDATE `%s` SET `userid`=?,`user_pass`=?,`sex`=?,`email`=?,`group_id`=?,`state`=?,`unban_time`=?,`expiration_time`=?,`logincount`=?,`lastlogin`=?,`last_ip`=?,`birthdate`=?,`character_slots`=?,`pincode`=?, `pincode_change`=?, `bank_vault`=?, `vip_time`=?, `old_group`=? WHERE `account_id` = '%d'",
#else
"UPDATE `%s` SET `userid`=?,`user_pass`=?,`sex`=?,`email`=?,`group_id`=?,`state`=?,`unban_time`=?,`expiration_time`=?,`logincount`=?,`lastlogin`=?,`last_ip`=?,`birthdate`=?,`character_slots`=?,`pincode`=?, `pincode_change`=?, `bank_vault`=? WHERE `account_id` = '%d'",
#endif
db->account_db, acc->account_id)
|| SQL_SUCCESS != SqlStmt_BindParam(stmt, 0, SQLDT_STRING, (void*)acc->userid, strlen(acc->userid))
|| SQL_SUCCESS != SqlStmt_BindParam(stmt, 1, SQLDT_STRING, (void*)acc->pass, strlen(acc->pass))
|| SQL_SUCCESS != SqlStmt_BindParam(stmt, 2, SQLDT_ENUM, (void*)&acc->sex, sizeof(acc->sex))
@ -644,6 +665,10 @@ static bool mmo_auth_tosql(AccountDB_SQL* db, const struct mmo_account* acc, boo
|| SQL_SUCCESS != SqlStmt_BindParam(stmt, 13, SQLDT_STRING, (void*)&acc->pincode, strlen(acc->pincode))
|| SQL_SUCCESS != SqlStmt_BindParam(stmt, 14, SQLDT_LONG, (void*)&acc->pincode_change, sizeof(acc->pincode_change))
|| SQL_SUCCESS != SqlStmt_BindParam(stmt, 15, SQLDT_INT, (void*)&acc->bank_vault, sizeof(acc->bank_vault))
#ifdef VIP_ENABLE
|| SQL_SUCCESS != SqlStmt_BindParam(stmt, 16, SQLDT_LONG, (void*)&acc->vip_time, sizeof(acc->vip_time))
|| SQL_SUCCESS != SqlStmt_BindParam(stmt, 17, SQLDT_INT, (void*)&acc->old_group, sizeof(acc->old_group))
#endif
|| SQL_SUCCESS != SqlStmt_Execute(stmt)
) {
SqlStmt_ShowDebug(stmt);

View File

@ -13,6 +13,9 @@
#include "../common/msg_conf.h"
#include "../common/cli.h"
#include "../common/ers.h"
#include "../common/utils.h"
#include "../common/mmo.h"
#include "../config/core.h"
#include "account.h"
#include "ipban.h"
#include "login.h"
@ -294,11 +297,16 @@ bool check_password(const char* md5key, int passwdenc, const char* passwd, const
}
//-----------------------------------------------------
// custom timestamp formatting (from eApp)
//-----------------------------------------------------
const char* timestamp2string(char* str, size_t size, time_t timestamp, const char* format)
{
/**
* Converting a timestamp is a srintf according to format
* safefr then strftime as it ensure \0 at end of string
* @param str, pointer to the destination string
* @param size, max length of the string
* @param timestamp, see unix epoch
* @param format, format to convert timestamp on, see strftime format
* @return the string of timestamp
*/
const char* timestamp2string(char* str, size_t size, time_t timestamp, const char* format){
size_t len = strftime(str, size, format, localtime(&timestamp));
memset(str + len, '\0', size - len);
return str;
@ -428,6 +436,132 @@ int parse_console(const char* buf){
return 0;
}
int chrif_send_accdata(int fd, uint32 aid) {
struct mmo_account acc;
time_t expiration_time = 0;
char email[40] = "";
int group_id = 0;
char birthdate[10+1] = "";
char pincode[PINCODE_LENGTH+1];
int bank_vault = 0;
char isvip = false;
uint8 char_slots = MIN_CHARS, char_vip = 0;
memset(pincode,0,PINCODE_LENGTH+1);
if( !accounts->load_num(accounts, &acc, aid) )
return -1;
else {
safestrncpy(email, acc.email, sizeof(email));
expiration_time = acc.expiration_time;
group_id = acc.group_id;
safestrncpy(birthdate, acc.birthdate, sizeof(birthdate));
safestrncpy(pincode, acc.pincode, sizeof(pincode));
bank_vault = acc.bank_vault;
#ifdef VIP_ENABLE
char_vip = login_config.vip_sys.char_increase;
if( acc.vip_time > time(NULL) ) {
isvip=true;
char_slots = login_config.char_per_account + char_vip;
} else
char_slots = login_config.char_per_account;
#endif
}
WFIFOHEAD(fd,79);
WFIFOW(fd,0) = 0x2717;
WFIFOL(fd,2) = aid;
safestrncpy((char*)WFIFOP(fd,6), email, 40);
WFIFOL(fd,46) = (uint32)expiration_time;
WFIFOB(fd,50) = (unsigned char)group_id;
WFIFOB(fd,51) = char_slots;
safestrncpy((char*)WFIFOP(fd,52), birthdate, 10+1);
safestrncpy((char*)WFIFOP(fd,63), pincode, 4+1 );
WFIFOL(fd,68) = (uint32)acc.pincode_change;
WFIFOL(fd,72) = bank_vault;
WFIFOB(fd,76) = isvip;
WFIFOB(fd,77) = char_vip;
WFIFOB(fd,78) = MAX_CHAR_BILLING; //TODO create a config for this
WFIFOSET(fd,79);
return 0;
}
int chrif_parse_reqaccdata(int fd, int cid, char *ip) {
if( RFIFOREST(fd) < 6 )
return 0;
else {
uint32 aid = RFIFOL(fd,2);
RFIFOSKIP(fd,6);
if( chrif_send_accdata(fd,aid) < 0 )
ShowNotice("Char-server '%s': account %d NOT found (ip: %s).\n", server[cid].name, aid, ip);
}
return 0;
}
int chrif_sendvipdata(int fd, struct mmo_account acc, char isvip) {
#ifdef VIP_ENABLE
uint8 buf[16];
WBUFW(buf,0) = 0x2743;
WBUFL(buf,2) = acc.account_id;
WBUFL(buf,6) = acc.vip_time;
WBUFB(buf,10) = isvip;
WBUFL(buf,11) = acc.group_id; //new group id
charif_sendallwos(-1,buf,15); //inform all char-servs of result
chrif_send_accdata(fd,acc.account_id); //refresh char with new setting
#endif
return 1;
}
/**
* Received a vip data reqest from char
* type is the query to perform
* &1 : Select info and update old_groupid
* &2 : Update vip time
* @param fd link to charserv
* @return 0 missing data, 1 succeed
*/
int chrif_parse_reqvipdata(int fd) {
#ifdef VIP_ENABLE
if( RFIFOREST(fd) < 11 )
return 0;
else { //request vip info
struct mmo_account acc;
int aid = RFIFOL(fd,2);
int8 type = RFIFOB(fd,6);
uint32 req_duration = RFIFOL(fd,7);
RFIFOSKIP(fd,11);
if( accounts->load_num(accounts, &acc, aid ) ){
time_t now = time(NULL);
time_t vip_time = acc.vip_time;
bool isvip = false;
if( type&2 ) vip_time = now + req_duration; // set new duration
if( now < vip_time ) { //isvip
if(acc.group_id != login_config.vip_sys.group) //only upd this if we're not vip already
acc.old_group = acc.group_id;
acc.group_id = login_config.vip_sys.group;
acc.char_slots = login_config.char_per_account + login_config.vip_sys.char_increase;
isvip = true;
} else { //expired
vip_time = 0;
acc.group_id = acc.old_group;
acc.old_group = 0;
acc.char_slots = login_config.char_per_account;
}
acc.vip_time = (int)vip_time;
accounts->save(accounts,&acc);
chrif_sendvipdata(fd,acc,isvip);
}
}
#endif
return 1;
}
//--------------------------------
// Packet parsing for char-servers
@ -555,54 +689,10 @@ int parse_fromchar(int fd){
}
break;
case 0x2716: // request account data
if( RFIFOREST(fd) < 6 )
return 0;
else{
struct mmo_account acc;
time_t expiration_time = 0;
char email[40] = "";
uint8 char_slots = 0;
int group_id = 0;
char birthdate[10+1] = "";
char pincode[PINCODE_LENGTH+1];
int account_id = RFIFOL(fd,2);
int bank_vault = 0;
memset(pincode,0,PINCODE_LENGTH+1);
RFIFOSKIP(fd,6);
if( !accounts->load_num(accounts, &acc, account_id) )
ShowNotice("Char-server '%s': account %d NOT found (ip: %s).\n", server[id].name, account_id, ip);
else{
safestrncpy(email, acc.email, sizeof(email));
expiration_time = acc.expiration_time;
group_id = acc.group_id;
char_slots = acc.char_slots;
safestrncpy(birthdate, acc.birthdate, sizeof(birthdate));
safestrncpy(pincode, acc.pincode, sizeof(pincode));
bank_vault = acc.bank_vault;
}
WFIFOHEAD(fd,76);
WFIFOW(fd,0) = 0x2717;
WFIFOL(fd,2) = account_id;
safestrncpy((char*)WFIFOP(fd,6), email, 40);
WFIFOL(fd,46) = (uint32)expiration_time;
WFIFOB(fd,50) = (unsigned char)group_id;
WFIFOB(fd,51) = char_slots;
safestrncpy((char*)WFIFOP(fd,52), birthdate, 10+1);
safestrncpy((char*)WFIFOP(fd,63), pincode, 4+1 );
WFIFOL(fd,68) = (uint32)acc.pincode_change;
WFIFOL(fd,72) = bank_vault;
WFIFOSET(fd,76);
}
break;
case 0x2716: chrif_parse_reqaccdata(fd,id,ip); break; // request account data
case 0x2719: // ping request from charserver
RFIFOSKIP(fd,2);
WFIFOHEAD(fd,2);
WFIFOW(fd,0) = 0x2718;
WFIFOSET(fd,2);
@ -973,6 +1063,8 @@ int parse_fromchar(int fd){
}
break;
case 0x2742: chrif_parse_reqvipdata(fd); break; //Vip sys
default:
ShowError("parse_fromchar: Unknown packet 0x%x from a char-server! Disconnecting!\n", command);
set_eof(fd);
@ -1026,10 +1118,12 @@ int mmo_auth_new(const char* userid, const char* pass, const char sex, const cha
safestrncpy(acc.birthdate, "0000-00-00", sizeof(acc.birthdate));
safestrncpy(acc.pincode, "", sizeof(acc.pincode));
acc.pincode_change = 0;
acc.char_slots = 0;
acc.char_slots = MIN_CHARS;
acc.bank_vault = 0;
#ifdef VIP_ENABLE
acc.vip_time = 0;
acc.old_group = 0;
#endif
if( !accounts->create(accounts, &acc) )
return 0;
@ -1638,8 +1732,7 @@ int parse_login(int fd)
}
void login_set_defaults()
{
void login_set_defaults() {
login_config.login_ip = INADDR_ANY;
login_config.login_port = 6900;
login_config.ipban_cleanup_interval = 60;
@ -1666,6 +1759,11 @@ void login_set_defaults()
login_config.client_hash_check = 0;
login_config.client_hash_nodes = NULL;
login_config.char_per_account = MAX_CHARS - MAX_CHAR_VIP - MAX_CHAR_BILLING;
#ifdef VIP_ENABLE
login_config.vip_sys.char_increase = MAX_CHAR_VIP;
login_config.vip_sys.group = 5;
#endif
}
//-----------------------------------
@ -1767,14 +1865,31 @@ int login_config_read(const char* cfgName)
login_config.client_hash_nodes = nnode;
}
} else if(strcmpi(w1, "chars_per_account") == 0) { //maxchars per account [Sirius]
login_config.char_per_account = atoi(w2);
if( login_config.char_per_account <= 0 || login_config.char_per_account > MAX_CHARS ) {
if( login_config.char_per_account > MAX_CHARS ) {
ShowWarning("Max chars per account '%d' exceeded limit. Defaulting to '%d'.\n", login_config.char_per_account, MAX_CHARS);
login_config.char_per_account = MAX_CHARS;
}
login_config.char_per_account = MIN_CHARS;
}
}
#ifdef VIP_ENABLE
else if(strcmpi(w1,"vip_group")==0)
login_config.vip_sys.group = cap_value(atoi(w2),0,99);
else if(strcmpi(w1,"vip_char_increase")==0) {
if(login_config.vip_sys.char_increase > (unsigned int) MAX_CHARS-login_config.char_per_account)
ShowWarning("vip_char_increase too high, can only go up to %d, according to your char_per_account config %d\n",
MAX_CHARS-login_config.char_per_account,login_config.char_per_account);
login_config.vip_sys.char_increase = cap_value(atoi(w2),0,MAX_CHARS-login_config.char_per_account);
}
#endif
else if(!strcmpi(w1, "import"))
login_config_read(w2);
else
if(!strcmpi(w1, "account.engine"))
else if(!strcmpi(w1, "account.engine"))
safestrncpy(login_config.account_engine, w2, sizeof(login_config.account_engine));
else
{// try the account engines
else {// try the account engines
int i;
for( i = 0; account_engines[i].constructor; ++i )
{

View File

@ -6,6 +6,7 @@
#include "../common/mmo.h" // NAME_LENGTH,SEX_*
#include "../common/core.h" // CORE_ST_LAST
#include "../config/core.h"
enum E_LOGINSERVER_ST
{
@ -58,7 +59,6 @@ struct client_hash_node {
};
struct Login_Config {
uint32 login_ip; // the address to bind to
uint16 login_port; // the port to bind to
unsigned int ipban_cleanup_interval; // interval (in seconds) to clean up expired IP bans
@ -86,6 +86,13 @@ struct Login_Config {
int client_hash_check; // flags for checking client md5
struct client_hash_node *client_hash_nodes; // linked list containg md5 hash for each gm group
int char_per_account; // number of characters an account can have
#ifdef VIP_ENABLE
struct {
unsigned int group;
unsigned int char_increase;
} vip_sys;
#endif
};
#define sex_num2str(num) ( (num == SEX_FEMALE ) ? 'F' : (num == SEX_MALE ) ? 'M' : 'S' )
@ -100,7 +107,7 @@ const char* login_msg_txt(int msg_number);
void login_do_final_msg(void);
#define MAX_SERVERS 30
#define MAX_SERVERS 30 //number of charserv loginserv can handle
extern struct mmo_char_server server[MAX_SERVERS];
extern struct Login_Config login_config;

View File

@ -7549,21 +7549,28 @@ ACMD_FUNC(mutearea)
ACMD_FUNC(rates)
{
char buf[CHAT_SIZE_MAX];
int base_exp_rate = 0, job_exp_rate = 0, item_rate = 0;
nullpo_ret(sd);
memset(buf, '\0', sizeof(buf));
// Display EXP and item rate increase for VIP.
if (pc_isvip(sd) && (battle_config.vip_base_exp_increase || battle_config.vip_job_exp_increase || battle_config.vip_drop_increase)) {
base_exp_rate += battle_config.vip_base_exp_increase;
job_exp_rate += battle_config.vip_job_exp_increase;
item_rate += battle_config.vip_drop_increase;
}
snprintf(buf, CHAT_SIZE_MAX, msg_txt(sd,1298), // Experience rates: Base %.2fx / Job %.2fx
battle_config.base_exp_rate/100., battle_config.job_exp_rate/100.);
(battle_config.base_exp_rate+base_exp_rate)/100., (battle_config.job_exp_rate+job_exp_rate)/100.);
clif_displaymessage(fd, buf);
snprintf(buf, CHAT_SIZE_MAX, msg_txt(sd,1299), // Normal Drop Rates: Common %.2fx / Healing %.2fx / Usable %.2fx / Equipment %.2fx / Card %.2fx
battle_config.item_rate_common/100., battle_config.item_rate_heal/100., battle_config.item_rate_use/100., battle_config.item_rate_equip/100., battle_config.item_rate_card/100.);
(battle_config.item_rate_common+item_rate)/100., (battle_config.item_rate_heal+item_rate)/100., (battle_config.item_rate_use+item_rate)/100., (battle_config.item_rate_equip+item_rate)/100., (battle_config.item_rate_card+item_rate)/100.);
clif_displaymessage(fd, buf);
snprintf(buf, CHAT_SIZE_MAX, msg_txt(sd,1300), // Boss Drop Rates: Common %.2fx / Healing %.2fx / Usable %.2fx / Equipment %.2fx / Card %.2fx
battle_config.item_rate_common_boss/100., battle_config.item_rate_heal_boss/100., battle_config.item_rate_use_boss/100., battle_config.item_rate_equip_boss/100., battle_config.item_rate_card_boss/100.);
(battle_config.item_rate_common_boss+item_rate)/100., (battle_config.item_rate_heal_boss+item_rate)/100., (battle_config.item_rate_use_boss+item_rate)/100., (battle_config.item_rate_equip_boss+item_rate)/100., (battle_config.item_rate_card_boss+item_rate)/100.);
clif_displaymessage(fd, buf);
snprintf(buf, CHAT_SIZE_MAX, msg_txt(sd,1301), // Other Drop Rates: MvP %.2fx / Card-Based %.2fx / Treasure %.2fx
battle_config.item_rate_mvp/100., battle_config.item_rate_adddrop/100., battle_config.item_rate_treasure/100.);
(battle_config.item_rate_mvp+item_rate)/100., (battle_config.item_rate_adddrop+item_rate)/100., (battle_config.item_rate_treasure+item_rate)/100.);
clif_displaymessage(fd, buf);
return 0;
@ -8295,7 +8302,7 @@ ACMD_FUNC(itemlist)
{
location = "storage";
items = sd->status.storage.items;
size = MAX_STORAGE;
size = sd->storage_size;
}
else
if( strcmp(command+1, "cartlist") == 0 )
@ -9181,6 +9188,65 @@ ACMD_FUNC(langtype)
return -1;
}
#ifdef VIP_ENABLE
ACMD_FUNC(vip)
{
struct map_session_data *pl_sd = NULL;
char * modif_p;
int viptime = 0;
nullpo_retr(-1, sd);
if (!message || !*message || sscanf(message, "%255s %23[^\n]",atcmd_output,atcmd_player_name) < 2) {
clif_displaymessage(fd, msg_txt(sd,700)); //Usage: @vip <time> <character name>
return -1;
}
atcmd_output[sizeof(atcmd_output)-1] = '\0';
modif_p = atcmd_output;
viptime = (int)solve_time(modif_p)/60; // Change to minutes
if (viptime == 0) {
clif_displaymessage(fd, msg_txt(sd,701)); // Invalid time for vip command.
clif_displaymessage(fd, msg_txt(sd,702)); // Time parameter format is +/-<value> to alter. y/a = Year, m = Month, d/j = Day, h = Hour, n/mn = Minute, s = Second.
return -1;
}
if ((pl_sd = map_nick2sd(atcmd_player_name)) == NULL) {
clif_displaymessage(fd, msg_txt(sd,3)); // Character not found.
return -1;
}
if (pc_get_group_level(pl_sd) > pc_get_group_level(sd)) {
clif_displaymessage(fd, msg_txt(sd,81)); // Your GM level don't authorise you to do this action on this player.
return -1;
}
pl_sd->vip.time += viptime;
if (pl_sd->vip.time <= 0) {
pl_sd->vip.time = 0;
pl_sd->vip.enabled = 0;
clif_displaymessage(pl_sd->fd, msg_txt(sd,703)); // GM has removed your VIP time.
clif_displaymessage(fd, msg_txt(sd,704)); // Player is no longer VIP.
} else {
int year,month,day,hour,minute,second;
char timestr[128];
split_time(pl_sd->vip.time*60,&year,&month,&day,&hour,&minute,&second);
sprintf(atcmd_output,msg_txt(sd,705),pl_sd->status.name,year,month,day,hour,minute); //%s is VIP for %d years, %d months, %d days, %d hours and %d minutes.
clif_displaymessage(pl_sd->fd, atcmd_output);
sprintf(atcmd_output,msg_txt(sd,706),year,month,day,hour,minute); //This player is now VIP for %d years, %d months, %d days, %d hours and %d minutes.
clif_displaymessage(fd, atcmd_output);
time2str(timestr,"%Y-%m-%d %H:%M",pl_sd->vip.time*60);
sprintf(atcmd_output,"%s : %s",msg_txt(sd,707),timestr); //You are VIP until :
clif_displaymessage(pl_sd->fd, atcmd_output);
clif_displaymessage(fd, atcmd_output);
}
chrif_req_vipActive(pl_sd, viptime, 3);
return 0;
}
#endif
#include "../custom/atcommand.inc"
/**
@ -9461,6 +9527,9 @@ void atcommand_basecommands(void) {
ACMD_DEF(channel),
ACMD_DEF(fontcolor),
ACMD_DEF(langtype),
#ifdef VIP_ENABLE
ACMD_DEF(vip),
#endif
};
AtCommandInfo* atcommand;
int i;

View File

@ -7233,10 +7233,20 @@ static const struct _battle_data {
{ "bowling_bash_area", &battle_config.bowling_bash_area, 0, 0, 20, },
{ "drop_rateincrease", &battle_config.drop_rateincrease, 0, 0, 1, },
{ "feature.banking", &battle_config.feature_banking, 1, 0, 1, },
{ "vip_storage_increase", &battle_config.vip_storage_increase, 0, 0, MAX_STORAGE-MIN_STORAGE, },
{ "vip_base_exp_increase", &battle_config.vip_base_exp_increase, 0, 0, INT_MAX, },
{ "vip_job_exp_increase", &battle_config.vip_job_exp_increase, 0, 0, INT_MAX, },
{ "vip_exp_penalty_base_normal", &battle_config.vip_exp_penalty_base_normal, 0, 0, INT_MAX, },
{ "vip_exp_penalty_job_normal", &battle_config.vip_exp_penalty_job_normal, 0, 0, INT_MAX, },
{ "vip_exp_penalty_base", &battle_config.vip_exp_penalty_base, 0, 0, INT_MAX, },
{ "vip_exp_penalty_job", &battle_config.vip_exp_penalty_job, 0, 0, INT_MAX, },
{ "vip_bm_increase", &battle_config.vip_bm_increase, 0, 0, INT_MAX, },
{ "vip_drop_increase", &battle_config.vip_drop_increase, 0, 0, INT_MAX, },
{ "vip_gemstone", &battle_config.vip_gemstone, 0, 0, 1, },
{ "mon_trans_disable_in_gvg", &battle_config.mon_trans_disable_in_gvg, 0, 0, 1, },
{ "homunculus_S_growth_level", &battle_config.hom_S_growth_level, 99, 0, MAX_LEVEL, },
{ "emblem_woe_change", &battle_config.emblem_woe_change, 0, 0, 1, },
{ "emblem_transparency_limit", &battle_config.emblem_transparency_limit, 80, 0, 100, },
{ "homunculus_S_growth_level", &battle_config.hom_S_growth_level, 99, 0, MAX_LEVEL, },
{ "emblem_woe_change", &battle_config.emblem_woe_change, 0, 0, 1, },
{ "emblem_transparency_limit", &battle_config.emblem_transparency_limit, 80, 0, 100, },
};
#ifndef STATS_OPT_OUT
/**

View File

@ -4,6 +4,9 @@
#ifndef _BATTLE_H_
#define _BATTLE_H_
#include "../common/mmo.h"
#include "../config/core.h"
// state of a single attack attempt; used in flee/def penalty calculations when mobbed
typedef enum damage_lv {
ATK_NONE, // not an attack
@ -496,6 +499,16 @@ extern struct Battle_Config
int bowling_bash_area;
int drop_rateincrease;
int feature_banking;
int vip_storage_increase;
int vip_base_exp_increase;
int vip_job_exp_increase;
int vip_bm_increase;
int vip_drop_increase;
int vip_gemstone;
int vip_exp_penalty_base_normal;
int vip_exp_penalty_base;
int vip_exp_penalty_job_normal;
int vip_exp_penalty_job;
int mon_trans_disable_in_gvg;
int emblem_woe_change;
int emblem_transparency_limit;

View File

@ -46,7 +46,7 @@ static const int packet_len_table[0x3d] = { // U - used, F - free
11,10,10, 0,11, -1,266,10, // 2b10-2b17: U->2b10, U->2b11, U->2b12, F->2b13, U->2b14, U->2b15, U->2b16, U->2b17
2,10, 2,-1,-1,-1, 2, 7, // 2b18-2b1f: U->2b18, U->2b19, U->2b1a, U->2b1b, U->2b1c, U->2b1d, U->2b1e, U->2b1f
-1,10, 8, 2, 2,14,19,19, // 2b20-2b27: U->2b20, U->2b21, U->2b22, U->2b23, U->2b24, U->2b25, U->2b26, U->2b27
10,10, 6, 0, 0, 6, -1, -1, // 2b28-2b2f: U->2b28, U->2b29, U->2b2a, F->2b2b, F->2b2c, U->2b2d, U->2b2e, U->2b2f
10,10, 6,15,11, 6,-1,-1, // 2b28-2b2f: U->2b28, U->2b29, U->2b2a, U->2b2b, U->2b2c, U->2b2d, U->2b2e, U->2b2f
};
//Used Packets:
@ -101,8 +101,8 @@ static const int packet_len_table[0x3d] = { // U - used, F - free
//2b28: Outgoing, chrif_save_bankdata -> 'send bank data to be saved'
//2b29: Incoming, chrif_load_bankdata -> 'received bank data for playeer to be loaded'
//2b2a: Outgoing, chrif_bankdata_request -> 'request bank data for charid'
//2b2b: FREE
//2b2c: FREE
//2b2b: Incoming, chrif_parse_ack_vipActive -> vip info result
//2b2c: Outgoing, chrif_req_vipActive -> request vip info
//2b2d: Outgoing, chrif_bsdata_request -> request bonus_script for pc_authok'ed char.
//2b2e: Outgoing, chrif_save_bsdata -> Send bonus_script of player for saving.
//2b2f: Incoming, chrif_load_bsdata -> received bonus_script of player for loading.
@ -1513,6 +1513,49 @@ void chrif_keepalive(int fd) {
void chrif_keepalive_ack(int fd) {
session[fd]->flag.ping = 0;/* reset ping state, we received a packet */
}
void chrif_parse_ack_vipActive(int fd) {
#ifdef VIP_ENABLE
int aid = RFIFOL(char_fd,2);
uint32 vip_time = RFIFOL(char_fd,6);
bool isvip = RFIFOB(char_fd,10);
uint32 groupid = RFIFOL(char_fd,11);
TBL_PC *sd = map_id2sd(aid);
if (sd && isvip) {
sd->vip.enabled = 1;
sd->vip.time = vip_time;
sd->group_id = groupid;
pc_group_pc_load(sd);
// Increase storage size for VIP.
sd->storage_size = battle_config.vip_storage_increase + MIN_STORAGE;
if (sd->storage_size > MAX_STORAGE) {
ShowError("intif_parse_ack_vipActive: Storage size for player %s (%d:%d) is larger than MAX_STORAGE. Storage size has been set to MAX_STORAGE.\n", sd->status.name, sd->status.account_id, sd->status.char_id);
sd->storage_size = MAX_STORAGE;
}
// Magic Stone requirement avoidance for VIP.
if (battle_config.vip_gemstone && pc_isvip(sd))
sd->special_state.no_gemstone = 2; // need to be done after status_calc_bl(bl,first);
}
#endif
}
int chrif_req_vipActive(TBL_PC *sd, int8 req_duration, int8 type) {
#ifdef VIP_ENABLE
if (CheckForCharServer() || sd == NULL)
return 0;
WFIFOHEAD(char_fd,11);
WFIFOW(char_fd,0) = 0x2b2c;
WFIFOL(char_fd,2) = sd->bl.id; // AID
WFIFOB(char_fd,6) = type; // type&1 - SQL SELECT, type&2 - SQL UPDATE
WFIFOL(char_fd,7) = req_duration;
WFIFOSET(char_fd,11);
#endif
return 0;
}
/*==========================================
*
*------------------------------------------*/
@ -1590,6 +1633,7 @@ int chrif_parse(int fd) {
case 0x2b25: chrif_deadopt(RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10)); break;
case 0x2b27: chrif_authfail(fd); break;
case 0x2b29: chrif_load_bankdata(fd); break;
case 0x2b2b: chrif_parse_ack_vipActive(fd); break;
case 0x2b2f: chrif_load_bsdata(fd); break;
default:
ShowError("chrif_parse : unknown packet (session #%d): 0x%x. Disconnecting.\n", fd, cmd);

View File

@ -67,6 +67,9 @@ int chrif_divorce(int partner_id1, int partner_id2);
int chrif_removefriend(int char_id, int friend_id);
int chrif_send_report(char* buf, int len);
void chrif_parse_ack_vipActive(int fd);
int chrif_req_vipActive(struct map_session_data *sd, int8 req_duration, int8 type);
int chrif_bsdata_request(int char_id);
int chrif_save_bsdata(struct map_session_data *sd);
int chrif_load_bsdata(int fd);

View File

@ -6252,6 +6252,7 @@ void clif_Bank_Check(struct map_session_data* sd) {
if(!cmd) cmd = 0x09A6; //default
info = &packet_db[sd->packet_ver][cmd];
len = info->len;
if(!len) return; //version as packet disable
// sd->state.banking = 1; //mark opening and closing
WBUFW(buf,0) = cmd;
@ -6274,8 +6275,8 @@ void clif_parse_BankCheck(int fd, struct map_session_data* sd) {
else {
struct s_packet_db* info = &packet_db[sd->packet_ver][RFIFOW(fd,0)];
int aid = RFIFOL(fd,info->pos[0]); //unused should we check vs fd ?
if(sd->status.account_id == aid) //since we have it let check it for extra security
clif_Bank_Check(sd);
if(sd->status.account_id == aid) //since we have it let check it for extra security
clif_Bank_Check(sd);
}
}
@ -6295,6 +6296,7 @@ void clif_bank_deposit(struct map_session_data *sd, enum e_BANKING_DEPOSIT_ACK r
if(!cmd) cmd = 0x09A8;
info = &packet_db[sd->packet_ver][cmd];
len = info->len;
if(!len) return; //version as packet disable
WBUFW(buf,0) = cmd;
WBUFW(buf,info->pos[0]) = (short)reason;
@ -6309,7 +6311,7 @@ void clif_bank_deposit(struct map_session_data *sd, enum e_BANKING_DEPOSIT_ACK r
* 09A7 <AID>L <Money>L (PACKET_CZ_REQ_BANKING_DEPOSIT)
*/
void clif_parse_BankDeposit(int fd, struct map_session_data* sd) {
nullpo_retv(sd);
nullpo_retv(sd);
if( !battle_config.feature_banking ) {
clif_colormes(sd,color_table[COLOR_RED],msg_txt(sd,1496)); //Banking is disabled
return;
@ -6337,14 +6339,15 @@ void clif_bank_withdraw(struct map_session_data *sd,enum e_BANKING_WITHDRAW_ACK
int cmd;
nullpo_retv(sd);
cmd = packet_db_ack[sd->packet_ver][ZC_ACK_BANKING_WITHDRAW];
if(!cmd) cmd = 0x09AA;
info = &packet_db[sd->packet_ver][cmd];
len = info->len;
if(!len) return; //version as packet disable
WBUFW(buf,0) = cmd;
WBUFW(buf,info->pos[0]) = (short)reason;
WBUFW(buf,info->pos[0]) = (short)reason;
WBUFQ(buf,info->pos[1]) = sd->status.bank_vault;/* money in the bank */
WBUFL(buf,info->pos[2]) = sd->status.zeny;/* how much zeny char has after operation */
@ -9606,6 +9609,10 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd)
#if PACKETVER >= 20070918
clif_partyinvitationstate(sd);
clif_equipcheckbox(sd);
#endif
#ifdef VIP_ENABLE
clif_display_pinfo(sd,ZC_PERSONAL_INFOMATION);
//clif_vip_display_info(sd,ZC_PERSONAL_INFOMATION_CHN);
#endif
if( (battle_config.bg_flee_penalty != 100 || battle_config.gvg_flee_penalty != 100) &&
(map_flag_gvg(sd->state.pmap) || map_flag_gvg(sd->bl.m) || map[sd->state.pmap].flag.battleground || map[sd->bl.m].flag.battleground) )
@ -16933,6 +16940,68 @@ void clif_update_rankingpoint(struct map_session_data *sd, int rankingtype, int
#endif
}
/**
* Transmit personal information to player. (rates)
* 08cb <packet len>.W <exp>.W <death>.W <drop>.W <DETAIL_EXP_INFO>7B (ZC_PERSONAL_INFOMATION)
* <InfoType>.B <Exp>.W <Death>.W <Drop>.W (DETAIL_EXP_INFO 0x8cb)
* 097b <packet len>.W <exp>.L <death>.L <drop>.L <DETAIL_EXP_INFO>13B (ZC_PERSONAL_INFOMATION2)
* 0981 <packet len>.W <exp>.W <death>.W <drop>.W <activity rate>.W <DETAIL_EXP_INFO>13B (ZC_PERSONAL_INFOMATION_CHN)
* <InfoType>.B <Exp>.L <Death>.L <Drop>.L (DETAIL_EXP_INFO 0x97b|0981)
* InfoType: 0 PCRoom, 1 Premium, 2 Server, 3 TPlus
*/
void clif_display_pinfo(struct map_session_data *sd, int cmdtype) {
if (sd) {
struct s_packet_db* info;
int16 len, szdetails = 13, maxinfotype = PINFO_MAX;
int cmd = 0, fd, i = 0, details_prem_penalty = 0;
int tot_baseexp = 0, total_penalty = 0, tot_drop = 0, factor = 1000;
int details_bexp[PINFO_MAX]= {map[sd->bl.m].adjust.bexp,battle_config.vip_base_exp_increase,battle_config.base_exp_rate,0 }; //TODO move me ?
int details_penalty[PINFO_MAX]= {0,0,battle_config.death_penalty_base,0 };
int details_drop[PINFO_MAX]= {0,battle_config.vip_drop_increase,battle_config.item_rate_common,0 };
cmd = packet_db_ack[sd->packet_ver][cmdtype];
info = &packet_db[sd->packet_ver][cmd];
len = info->len; //this is the base len without details
if(!len) return; //version as packet disable
if (cmdtype == ZC_PERSONAL_INFOMATION && len == 10) { //8cb version
szdetails = 7;
maxinfotype = 3;
factor = 1;
}
// Need to alter penalty data for VIP whether the system is enabled or not.
details_prem_penalty = battle_config.death_penalty_base;
#ifdef VIP_ENABLE
details_prem_penalty = battle_config.death_penalty_base * (battle_config.vip_exp_penalty_base_normal - 1);
if (pc_isvip(sd)) details_prem_penalty = battle_config.death_penalty_base * (battle_config.vip_exp_penalty_base - 1);
details_prem_penalty = max(0,details_prem_penalty);
#endif
details_penalty[PINFO_PREMIUM] = details_prem_penalty;
fd = sd->fd;
WFIFOHEAD(fd,len+maxinfotype*szdetails);
WFIFOW(fd,0) = cmd;
for (i = 0; i < maxinfotype; i++) {
WFIFOB(fd,info->pos[4]+(i*szdetails)) = i; //infotype //0 PCRoom, 1 Premium, 2 Server, 3 TPlus
WFIFOW(fd,info->pos[5]+(i*szdetails)) = 0;
tot_baseexp += details_bexp[i]*factor;
WFIFOW(fd,info->pos[6]+(i*szdetails)) = details_penalty[i]*factor;
total_penalty += details_penalty[i]*factor;
WFIFOW(fd,info->pos[7]+(i*szdetails)) = details_drop[i]*factor;
tot_drop += details_drop[i]*factor;
len += szdetails;
}
WFIFOW(fd,info->pos[0]) = len; //packetlen
WFIFOW(fd,info->pos[1]) = tot_baseexp;
WFIFOW(fd,info->pos[2]) = total_penalty; //6 8
WFIFOW(fd,info->pos[3]) = tot_drop; //8 12
if (cmdtype == ZC_PERSONAL_INFOMATION_CHN)
WFIFOW(fd,info->pos[8]) = 0; //activity rate case of event ??
WFIFOSET(fd,len);
}
}
#ifdef DUMP_UNKNOWN_PACKET
void DumpUnknow(int fd,TBL_PC *sd,int cmd,int packet_len){
const char* packet_txt = "save/packet.txt";
@ -17570,15 +17639,18 @@ void packetdb_readdb(void)
{ clif_parse_ranklist, "ranklist"},
{NULL,NULL}
};
struct {
struct {
char *name; //function name
int funcidx; //
int funcidx; //
} clif_ack_func[]={ //hash
{ "ZC_ACK_OPEN_BANKING", ZC_ACK_OPEN_BANKING},
{ "ZC_ACK_BANKING_DEPOSIT", ZC_ACK_BANKING_DEPOSIT},
{ "ZC_ACK_BANKING_WITHDRAW", ZC_ACK_BANKING_WITHDRAW},
{ "ZC_BANKING_CHECK", ZC_BANKING_CHECK},
};
{ "ZC_ACK_OPEN_BANKING", ZC_ACK_OPEN_BANKING},
{ "ZC_ACK_BANKING_DEPOSIT", ZC_ACK_BANKING_DEPOSIT},
{ "ZC_ACK_BANKING_WITHDRAW", ZC_ACK_BANKING_WITHDRAW},
{ "ZC_BANKING_CHECK", ZC_BANKING_CHECK},
{ "ZC_BANKING_CHECK", ZC_BANKING_CHECK},
{ "ZC_PERSONAL_INFOMATION", ZC_PERSONAL_INFOMATION},
{ "ZC_PERSONAL_INFOMATION_CHN", ZC_PERSONAL_INFOMATION_CHN},
};
// initialize packet_db[SERVER] from hardcoded packet_len_table[] values
memset(packet_db,0,sizeof(packet_db));

View File

@ -40,11 +40,14 @@ enum
};
enum e_packet_ack {
ZC_ACK_OPEN_BANKING = 0,
ZC_ACK_BANKING_DEPOSIT,
ZC_ACK_BANKING_WITHDRAW,
ZC_BANKING_CHECK,
MAX_ACK_FUNC //auto upd len
ZC_ACK_OPEN_BANKING = 0,
ZC_ACK_BANKING_DEPOSIT,
ZC_ACK_BANKING_WITHDRAW,
ZC_BANKING_CHECK,
ZC_PERSONAL_INFOMATION,
ZC_PERSONAL_INFOMATION_CHN,
//add otehr here
MAX_ACK_FUNC //auto upd len
};
struct s_packet_db {
@ -348,6 +351,14 @@ enum clif_messages {
ADDITEM_TO_CART_FAIL_COUNT = 0x1,
};
enum e_personalinfo {
PINFO_BASIC = 0,
PINFO_PREMIUM,
PINFO_SERVER,
PINFO_CAFE,
PINFO_MAX,
};
int clif_setip(const char* ip);
void clif_setbindip(const char* ip);
void clif_setport(uint16 port);
@ -773,6 +784,8 @@ void clif_search_store_info_click_ack(struct map_session_data* sd, short x, shor
void clif_cashshop_result( struct map_session_data* sd, uint16 item_id, uint16 result );
void clif_cashshop_open( struct map_session_data* sd );
void clif_display_pinfo(struct map_session_data *sd, int type);
/**
* 3CeAM
**/

View File

@ -2249,13 +2249,23 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
if (map[m].flag.nobaseexp || !md->db->base_exp)
base_exp = 0;
else
base_exp = (unsigned int)cap_value(md->db->base_exp * per * bonus/100. * map[m].adjust.bexp/100., 1, UINT_MAX);
else {
int vip_bonus = 0;
// Increase base EXP rate for VIP.
if (battle_config.vip_base_exp_increase && (sd && pc_isvip(sd)))
vip_bonus += battle_config.vip_base_exp_increase;
base_exp = (unsigned int)cap_value(md->db->base_exp * per * (bonus+vip_bonus)/100. * map[m].adjust.bexp/100., 1, UINT_MAX);
}
if (map[m].flag.nojobexp || !md->db->job_exp || md->dmglog[i].flag == MDLF_HOMUN) //Homun earned job-exp is always lost.
job_exp = 0;
else
job_exp = (unsigned int)cap_value(md->db->job_exp * per * bonus/100. * map[m].adjust.jexp/100., 1, UINT_MAX);
else {
int vip_bonus = 0;
// Increase job EXP rate for VIP.
if (battle_config.vip_job_exp_increase && (sd && pc_isvip(sd)))
vip_bonus += battle_config.vip_job_exp_increase;
job_exp = (unsigned int)cap_value(md->db->job_exp * per * (bonus+vip_bonus)/100. * map[m].adjust.jexp/100., 1, UINT_MAX);
}
if ( ( temp = tmpsd[i]->status.party_id)>0 ) {
int j;
@ -2371,6 +2381,11 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
// Increase drop rate if user has SC_ITEMBOOST
if (sd && sd->sc.data[SC_ITEMBOOST]) // now rig the drop rate to never be over 90% unless it is originally >90%.
drop_rate = max(drop_rate,cap_value((int)(0.5+drop_rate*(sd->sc.data[SC_ITEMBOOST]->val1)/100.),0,9000));
// Increase item drop rate for VIP.
if (battle_config.vip_drop_increase && (sd && pc_isvip(sd))) {
drop_rate += (int)(0.5 + (drop_rate * battle_config.vip_drop_increase) / 10000.);
drop_rate = min(drop_rate,10000); //cap it to 100%
}
#ifdef RENEWAL_DROP
if( drop_modifier != 100 ) {
drop_rate = drop_rate * drop_modifier / 100;

View File

@ -1276,6 +1276,8 @@ int pc_reg_received(struct map_session_data *sd)
chrif_skillcooldown_request(sd->status.account_id, sd->status.char_id);
chrif_bankdata_request(sd->status.account_id, sd->status.char_id);
chrif_bsdata_request(sd->status.char_id);
sd->storage_size = MIN_STORAGE; //default to min
chrif_req_vipActive(sd, 0, 1); // request VIP informations
intif_Mail_requestinbox(sd->status.char_id, 0); // MAIL SYSTEM - Request Mail Inbox
intif_request_questlog(sd);
@ -2489,7 +2491,7 @@ int pc_bonus(struct map_session_data *sd,int type,int val)
sd->special_state.no_misc_damage = cap_value(val,0,100);
break;
case SP_NO_GEMSTONE:
if(sd->state.lr_flag != 2)
if(sd->state.lr_flag != 2 && sd->special_state.no_gemstone != 2)
sd->special_state.no_gemstone = 1;
break;
case SP_INTRAVISION: // Maya Purple Card effect allowing to see Hiding/Cloaking people [DracoRPG]
@ -5877,8 +5879,11 @@ static void pc_calcexp(struct map_session_data *sd, unsigned int *base_exp, unsi
(int)(status_get_lv(src) - sd->status.base_level) >= 20)
bonus += 15; // pk_mode additional exp if monster >20 levels [Valaris]
if (sd->sc.data[SC_EXPBOOST])
bonus += sd->sc.data[SC_EXPBOOST]->val1;
if (sd->sc.data[SC_EXPBOOST]) {
bonus += sd->sc.data[SC_EXPBOOST]->val1;
if( battle_config.vip_bm_increase && pc_isvip(sd) ) // Increase Battle Manual EXP rate for VIP.
bonus += ( sd->sc.data[SC_EXPBOOST]->val1 / battle_config.vip_bm_increase );
}
*base_exp = (unsigned int) cap_value(*base_exp + (double)*base_exp * bonus/100., 1, UINT_MAX);
@ -6928,37 +6933,38 @@ int pc_dead(struct map_session_data *sd,struct block_list *src)
&& !map[sd->bl.m].flag.noexppenalty && !map_flag_gvg(sd->bl.m)
&& !sd->sc.data[SC_BABY] && !sd->sc.data[SC_LIFEINSURANCE])
{
unsigned int base_penalty =0;
if (battle_config.death_penalty_base > 0) {
unsigned int base_penalty = battle_config.death_penalty_base, job_penalty = battle_config.death_penalty_job;
#ifdef VIP_ENABLE
if(pc_isvip(sd)){
base_penalty = base_penalty*battle_config.vip_exp_penalty_base;
job_penalty = job_penalty*battle_config.vip_exp_penalty_job;
}
else {
base_penalty = base_penalty*battle_config.vip_exp_penalty_base_normal;
job_penalty = job_penalty*battle_config.vip_exp_penalty_job_normal;
}
#endif
if (base_penalty > 0) {
switch (battle_config.death_penalty_type) {
case 1:
base_penalty = (unsigned int) ((double)pc_nextbaseexp(sd) * (double)battle_config.death_penalty_base/10000);
break;
case 2:
base_penalty = (unsigned int) ((double)sd->status.base_exp * (double)battle_config.death_penalty_base/10000);
break;
case 1: base_penalty = (uint32) ((double)(pc_nextbaseexp(sd) * base_penalty)/10000); break;
case 2: base_penalty = (uint32) ((double)(sd->status.base_exp * base_penalty)/10000); break;
}
if(base_penalty) {
if (base_penalty > 0){ //recheck after altering to speedup
if (battle_config.pk_mode && src && src->type==BL_PC)
base_penalty*=2;
sd->status.base_exp -= min(sd->status.base_exp, base_penalty);
clif_updatestatus(sd,SP_BASEEXP);
}
}
if(battle_config.death_penalty_job > 0) {
base_penalty = 0;
if(job_penalty > 0) {
switch (battle_config.death_penalty_type) {
case 1:
base_penalty = (unsigned int) ((double)pc_nextjobexp(sd) * (double)battle_config.death_penalty_job/10000);
break;
case 2:
base_penalty = (unsigned int) ((double)sd->status.job_exp * (double)battle_config.death_penalty_job/10000);
break;
case 1: job_penalty = (uint32) ((double)(pc_nextjobexp(sd) * job_penalty)/10000); break;
case 2: job_penalty = (uint32) ((double)(sd->status.job_exp * job_penalty)/10000); break;
}
if(base_penalty) {
if(job_penalty) {
if (battle_config.pk_mode && src && src->type==BL_PC)
base_penalty*=2;
sd->status.job_exp -= min(sd->status.job_exp, base_penalty);
job_penalty*=2;
sd->status.job_exp -= min(sd->status.job_exp, job_penalty);
clif_updatestatus(sd,SP_JOBEXP);
}
}
@ -9087,7 +9093,7 @@ int pc_check_available_item(struct map_session_data *sd) {
}
if( battle_config.item_check&4 ) { // Check for invalid(ated) items in storage.
for( i = 0; i < MAX_STORAGE; i++ ) {
for( i = 0; i < sd->storage_size; i++ ) {
it = sd->status.storage.items[i].nameid;
if( it && !itemdb_available(it) ) {

View File

@ -201,7 +201,7 @@ struct map_session_data {
unsigned int no_castcancel : 1;
unsigned int no_castcancel2 : 1;
unsigned int no_sizefix : 1;
unsigned int no_gemstone : 1;
unsigned int no_gemstone : 2;
unsigned int intravision : 1; // Maya Purple Card effect [DracoRPG]
unsigned int perfect_hiding : 1; // [Valaris]
unsigned int no_knockback : 1;
@ -213,7 +213,7 @@ struct map_session_data {
unsigned int permissions;/* group permissions */
int langtype;
int packet_ver; // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 ... 18
uint32 packet_ver; // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 ... 18
struct mmo_charstatus status;
struct registry save_reg;
@ -551,6 +551,14 @@ struct map_session_data {
} c_marker;
bool flicker;
int storage_size; // Holds player storage size (VIP system).
#ifdef VIP_ENABLE
struct {
unsigned int enabled;
unsigned int time;
} vip;
#endif
//Timed bonus 'bonus_script' struct [Cydh]
struct s_script {
struct script_code *script;
@ -683,7 +691,11 @@ struct {
#define pc_ishiding(sd) ( (sd)->sc.option&(OPTION_HIDE|OPTION_CLOAK|OPTION_CHASEWALK) )
#define pc_iscloaking(sd) ( !((sd)->sc.option&OPTION_CHASEWALK) && ((sd)->sc.option&OPTION_CLOAK) )
#define pc_ischasewalk(sd) ( (sd)->sc.option&OPTION_CHASEWALK )
#ifdef VIP_ENABLE
#define pc_isvip(sd) ( sd->vip.enabled ? 1 : 0 )
#else
#define pc_isvip(sd) ( 0 )
#endif
#ifdef NEW_CARTS
#define pc_iscarton(sd) ( (sd)->sc.data[SC_PUSH_CART] )
#else

View File

@ -18010,6 +18010,7 @@ BUILDIN_FUNC(getserverdef) {
case 7: script_pushint(st,MAX_GUILDLEVEL); break;
case 8: script_pushint(st,MAX_GUILD_STORAGE); break;
case 9: script_pushint(st,MAX_BG_MEMBERS); break;
case 10: script_pushint(st,VIP_SCRIPT); break;
default:
ShowWarning("buildin_getserverdef: unknown type %d.\n", type);
script_pushint(st,0);
@ -18018,6 +18019,74 @@ BUILDIN_FUNC(getserverdef) {
return 0;
}
#ifdef VIP_ENABLE
/* Returns various information about a player's VIP status.
* vip_status <type>,{"<character name>"};
* Note: VIP System needs to be enabled.
*/
BUILDIN_FUNC(vip_status) {
TBL_PC *sd;
char *vip_str = (char *)aMalloc(24*sizeof(char));
time_t now = time(NULL);
int type = script_getnum(st, 2);
if (script_hasdata(st, 3))
sd = map_nick2sd(script_getstr(st, 3));
else
sd = script_rid2sd(st);
if (sd == NULL)
return 0;
switch(type) {
case 0: // Get VIP status.
script_pushint(st, pc_isvip(sd));
break;
case 1: // Get VIP expire date.
if (pc_isvip(sd)) {
time_t viptime = (time_t)sd->vip.time;
strftime(vip_str, 24, "%Y-%m-%d %H:%M", localtime(&viptime));
vip_str[24] = '\0';
script_pushstr(st, vip_str);
} else
script_pushint(st, 0);
break;
case 2: // Get remaining time.
if (pc_isvip(sd)) {
time_t viptime = (time_t)sd->vip.time;
strftime(vip_str, 24, "%Y-%m-%d %H:%M", localtime(&viptime - now));
vip_str[24] = '\0';
script_pushstr(st, vip_str);
} else
script_pushint(st, 0);
break;
}
return 0;
}
/* Adds or removes VIP time in minutes.
* vip_time <time>,{"<character name>"};
* If time < 0 remove time, else add time.
* Note: VIP System needs to be enabled.
*/
BUILDIN_FUNC(vip_time) {
TBL_PC *sd;
int time = script_getnum(st, 2) * 60; // Convert since it's given in minutes.
if (script_hasdata(st, 3))
sd = map_nick2sd(script_getstr(st, 3));
else
sd = script_rid2sd(st);
if (sd == NULL)
return 0;
chrif_req_vipActive(sd, time, 2);
return 0;
}
#endif
/*==========================================
* Turns a player into a monster and grants SC attribute effect. [malufett/Hercules]
* montransform <monster name/ID>, <duration>, <sc type>, <val1>, <val2>, <val3>, <val4>;
@ -18636,6 +18705,10 @@ struct script_function buildin_func[] = {
BUILDIN_DEF(is_clientver,"ii?"),
BUILDIN_DEF(getserverdef,"i"),
BUILDIN_DEF2(montransform, "transform", "vii????"), // Monster Transform [malufett/Hercules]
#ifdef VIP_ENABLE
BUILDIN_DEF(vip_status,"i?"),
BUILDIN_DEF(vip_time,"i?"),
#endif
BUILDIN_DEF(bonus_script,"si???"),
#include "../custom/script_def.inc"

View File

@ -13714,7 +13714,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
* Warlock
**/
case WL_COMET:
if( skill_check_pc_partner(sd,skill_id,&skill_lv,1,0) <= 0
if( skill_check_pc_partner(sd,skill_id,&skill_lv,1,0) <= 0 && require.itemid[0]
&& sd->special_state.no_gemstone == 0
&& ((i = pc_search_inventory(sd,require.itemid[0])) < 0 || sd->status.inventory[i].amount < require.amount[0]) ) {
//clif_skill_fail(sd,skill_id,USESKILL_FAIL_NEED_ITEM,require.amount[0],require.itemid[0]);
@ -14454,11 +14454,11 @@ struct skill_condition skill_get_requirement(struct map_session_data* sd, uint16
continue;
break;
case AB_ADORAMUS:
if( itemid_isgemstone(skill_db[idx].require.itemid[i]) && skill_check_pc_partner(sd,skill_id,&skill_lv, 1, 2) )
if( itemid_isgemstone(skill_db[idx].require.itemid[i]) && (sd->special_state.no_gemstone == 2 || skill_check_pc_partner(sd,skill_id,&skill_lv, 1, 2)) )
continue;
break;
case WL_COMET:
if( itemid_isgemstone(skill_db[idx].require.itemid[i]) && skill_check_pc_partner(sd,skill_id,&skill_lv, 1, 0) )
if( itemid_isgemstone(skill_db[idx].require.itemid[i]) && (sd->special_state.no_gemstone == 2 || skill_check_pc_partner(sd,skill_id,&skill_lv, 1, 0)) )
continue;
break;
case GN_FIRE_EXPANSION:
@ -14481,21 +14481,25 @@ struct skill_condition skill_get_requirement(struct map_session_data* sd, uint16
req.itemid[i] = skill_db[idx].require.itemid[i];
req.amount[i] = skill_db[idx].require.amount[i];
if( itemid_isgemstone(req.itemid[i]) && skill_id != HW_GANBANTEIN )
{
if( sd->special_state.no_gemstone )
{ // All gem skills except Hocus Pocus and Ganbantein can cast for free with Mistress card -helvetica
if( skill_id != SA_ABRACADABRA )
req.itemid[i] = req.amount[i] = 0;
else if( --req.amount[i] < 1 )
req.amount[i] = 1; // Hocus Pocus always use at least 1 gem
}
if(sc && sc->data[SC_INTOABYSS])
{
if( skill_id != SA_ABRACADABRA )
req.itemid[i] = req.amount[i] = 0;
else if( --req.amount[i] < 1 )
req.amount[i] = 1; // Hocus Pocus always use at least 1 gem
// Check requirement for gemstone.
if (itemid_isgemstone(req.itemid[i])) {
if( sd->special_state.no_gemstone == 2 ) // Remove all Magic Stone required for all skills for VIP.
req.itemid[i] = req.amount[i] = 0;
else {
if( sd->special_state.no_gemstone )
{ // All gem skills except Hocus Pocus and Ganbantein can cast for free with Mistress card -helvetica
if( skill_id != SA_ABRACADABRA )
req.itemid[i] = req.amount[i] = 0;
else if( --req.amount[i] < 1 )
req.amount[i] = 1; // Hocus Pocus always use at least 1 gem
}
if(sc && sc->data[SC_INTOABYSS])
{
if( skill_id != SA_ABRACADABRA )
req.itemid[i] = req.amount[i] = 0;
else if( --req.amount[i] < 1 )
req.amount[i] = 1; // Hocus Pocus always use at least 1 gem
}
}
}
if( skill_id >= HT_SKIDTRAP && skill_id <= HT_TALKIEBOX && pc_checkskill(sd, RA_RESEARCHTRAP) > 0){

View File

@ -2636,10 +2636,10 @@ int status_calc_pc_(struct map_session_data* sd, bool first)
wa->atk2 = refine_info[wlv].bonus[r-1] / 100;
#ifdef RENEWAL
wa->matk += sd->inventory_data[index]->matk;
wa->wlv = wlv;
if( r ) // Renewal magic attack refine bonus
wa->matk += refine_info[wlv].bonus[r-1] / 100;
wa->matk += sd->inventory_data[index]->matk;
wa->wlv = wlv;
if( r ) // Renewal magic attack refine bonus
wa->matk += refine_info[wlv].bonus[r-1] / 100;
#endif
// Overrefine bonus.
@ -4988,7 +4988,7 @@ static unsigned short status_calc_ematk(struct block_list *bl, struct status_cha
matk += 40 + 30 * sc->data[SC_ODINS_POWER]->val1; // 70 lvl1, 100lvl2
if(sc->data[SC_IZAYOI])
matk += 50 * sc->data[SC_IZAYOI]->val1;
return (unsigned short)cap_value(matk,0,USHRT_MAX);
return (unsigned short)cap_value(matk,0,USHRT_MAX);
}
#endif
/**

View File

@ -107,7 +107,7 @@ int storage_storageopen(struct map_session_data *sd)
sd->state.storage_flag = 1;
storage_sortitem(sd->status.storage.items, ARRAYLENGTH(sd->status.storage.items));
clif_storagelist(sd, sd->status.storage.items, ARRAYLENGTH(sd->status.storage.items));
clif_updatestorageamount(sd, sd->status.storage.storage_amount, MAX_STORAGE);
clif_updatestorageamount(sd, sd->status.storage.storage_amount, sd->storage_size);
return 0;
}
@ -162,7 +162,7 @@ static int storage_additem(struct map_session_data* sd, struct item* item_data,
if( itemdb_isstackable2(data) )
{//Stackable
for( i = 0; i < MAX_STORAGE; i++ )
for( i = 0; i < sd->storage_size; i++ )
{
if( compare_item(&stor->items[i], item_data) )
{// existing items found, stack them
@ -176,8 +176,8 @@ static int storage_additem(struct map_session_data* sd, struct item* item_data,
}
// find free slot
ARR_FIND( 0, MAX_STORAGE, i, stor->items[i].nameid == 0 );
if( i >= MAX_STORAGE )
ARR_FIND( 0, sd->storage_size, i, stor->items[i].nameid == 0 );
if( i >= sd->storage_size )
return 1;
// add item to slot
@ -185,7 +185,7 @@ static int storage_additem(struct map_session_data* sd, struct item* item_data,
stor->storage_amount++;
stor->items[i].amount = amount;
clif_storageitemadded(sd,&stor->items[i],i,amount);
clif_updatestorageamount(sd, stor->storage_amount, MAX_STORAGE);
clif_updatestorageamount(sd, stor->storage_amount, sd->storage_size);
return 0;
}
@ -203,7 +203,7 @@ int storage_delitem(struct map_session_data* sd, int n, int amount)
{
memset(&sd->status.storage.items[n],0,sizeof(sd->status.storage.items[0]));
sd->status.storage.storage_amount--;
if( sd->state.storage_flag == 1 ) clif_updatestorageamount(sd, sd->status.storage.storage_amount, MAX_STORAGE);
if( sd->state.storage_flag == 1 ) clif_updatestorageamount(sd, sd->status.storage.storage_amount, sd->storage_size);
}
if( sd->state.storage_flag == 1 ) clif_storageitemremoved(sd,n,amount);
return 0;
@ -220,7 +220,7 @@ int storage_storageadd(struct map_session_data* sd, int index, int amount)
{
nullpo_ret(sd);
if( sd->status.storage.storage_amount > MAX_STORAGE )
if( sd->status.storage.storage_amount > sd->storage_size )
return 0; // storage full
if( index < 0 || index >= MAX_INVENTORY )
@ -253,7 +253,7 @@ int storage_storageget(struct map_session_data* sd, int index, int amount)
{
int flag;
if( index < 0 || index >= MAX_STORAGE )
if( index < 0 || index >= sd->storage_size )
return 0;
if( sd->status.storage.items[index].nameid <= 0 )
@ -281,11 +281,11 @@ int storage_storageaddfromcart(struct map_session_data* sd, int index, int amoun
{
nullpo_ret(sd);
if( sd->status.storage.storage_amount > MAX_STORAGE )
return 0; // storage full / storage closed
if( sd->status.storage.storage_amount > sd->storage_size )
return 0; // storage full / storage closed
if( index < 0 || index >= MAX_CART )
return 0;
return 0;
if( sd->status.cart[index].nameid <= 0 )
return 0; //No item there.
@ -311,7 +311,7 @@ int storage_storagegettocart(struct map_session_data* sd, int index, int amount)
short flag;
nullpo_ret(sd);
if( index < 0 || index >= MAX_STORAGE )
if( index < 0 || index >= sd->storage_size )
return 0;
if( sd->status.storage.items[index].nameid <= 0 )

View File

@ -2191,7 +2191,7 @@ int unit_skillcastcancel(struct block_list *bl,int type)
return 0;
if (sd && (sd->special_state.no_castcancel2 ||
((sd->sc.data[SC_UNLIMITEDHUMMINGVOICE] || sd->special_state.no_castcancel) && !map_flag_gvg(bl->m) && !map[bl->m].flag.battleground))) // fixed flags being read the wrong way around [blackhole89]
((sd->sc.data[SC_UNLIMITEDHUMMINGVOICE] || sd->special_state.no_castcancel) && !map_flag_gvg(bl->m) && !map[bl->m].flag.battleground))) // fixed flags being read the wrong way around [blackhole89]
return 0;
}

View File

@ -138,6 +138,7 @@
<ClInclude Include="..\3rdparty\libconfig\wincompat.h" />
<ClInclude Include="..\3rdparty\mt19937ar\mt19937ar.h" />
<ClInclude Include="..\src\common\cbasetypes.h" />
<ClInclude Include="..\src\common\conf.h" />
<ClInclude Include="..\src\common\core.h" />
<ClInclude Include="..\src\common\db.h" />
<ClInclude Include="..\src\common\ers.h" />
@ -179,6 +180,7 @@
<ClCompile Include="..\3rdparty\libconfig\scanner.c" />
<ClCompile Include="..\3rdparty\libconfig\strbuf.c" />
<ClCompile Include="..\3rdparty\mt19937ar\mt19937ar.c" />
<ClCompile Include="..\src\common\conf.c" />
<ClCompile Include="..\src\common\core.c" />
<ClCompile Include="..\src\common\db.c" />
<ClCompile Include="..\src\common\ers.c" />
@ -214,4 +216,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>

View File

@ -106,6 +106,11 @@
<ClCompile Include="..\src\common\raconf.c">
<Filter>common</Filter>
</ClCompile>
<ClCompile Include="..\src\common\msg_conf.c" />
<ClCompile Include="..\src\common\cli.c" />
<ClCompile Include="..\src\common\conf.c">
<Filter>common</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\src\common\cbasetypes.h">
@ -228,6 +233,11 @@
<ClInclude Include="..\src\common\raconf.h">
<Filter>common</Filter>
</ClInclude>
<ClInclude Include="..\src\common\msg_conf.h" />
<ClInclude Include="..\src\common\cli.h" />
<ClInclude Include="..\src\common\conf.h">
<Filter>common</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Filter Include="common">
@ -246,4 +256,4 @@
<UniqueIdentifier>{9e8badd7-548f-4eb4-9e87-613e87e772ff}</UniqueIdentifier>
</Filter>
</ItemGroup>
</Project>
</Project>

View File

@ -138,6 +138,7 @@
<ClInclude Include="..\3rdparty\libconfig\scanner.h" />
<ClInclude Include="..\3rdparty\libconfig\strbuf.h" />
<ClInclude Include="..\3rdparty\libconfig\wincompat.h" />
<ClInclude Include="..\src\common\conf.h" />
<ClInclude Include="..\src\common\mempool.h" />
<ClInclude Include="..\src\common\mutex.h" />
<ClInclude Include="..\src\common\raconf.h" />
@ -172,6 +173,7 @@
<ClCompile Include="..\3rdparty\libconfig\scanctx.c" />
<ClCompile Include="..\3rdparty\libconfig\scanner.c" />
<ClCompile Include="..\3rdparty\libconfig\strbuf.c" />
<ClCompile Include="..\src\common\conf.c" />
<ClCompile Include="..\src\common\mempool.c" />
<ClCompile Include="..\src\common\mutex.c" />
<ClCompile Include="..\src\common\raconf.c" />
@ -200,4 +202,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>

View File

@ -82,6 +82,11 @@
<ClCompile Include="..\src\common\raconf.c">
<Filter>common</Filter>
</ClCompile>
<ClCompile Include="..\src\common\msg_conf.c" />
<ClCompile Include="..\src\common\cli.c" />
<ClCompile Include="..\src\common\conf.c">
<Filter>common</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\src\login\account.h">
@ -180,6 +185,11 @@
<ClInclude Include="..\src\common\raconf.h">
<Filter>common</Filter>
</ClInclude>
<ClInclude Include="..\src\common\msg_conf.h" />
<ClInclude Include="..\src\common\cli.h" />
<ClInclude Include="..\src\common\conf.h">
<Filter>common</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Filter Include="common">
@ -198,4 +208,4 @@
<UniqueIdentifier>{779e8145-9bb2-4a88-9149-60586ab0bdd4}</UniqueIdentifier>
</Filter>
</ItemGroup>
</Project>
</Project>

View File

@ -142,6 +142,7 @@
<ClInclude Include="..\3rdparty\mt19937ar\mt19937ar.h" />
<ClInclude Include="..\src\common\cbasetypes.h" />
<ClInclude Include="..\src\common\core.h" />
<ClInclude Include="..\src\common\conf.h" />
<ClInclude Include="..\src\common\db.h" />
<ClInclude Include="..\src\common\ers.h" />
<ClInclude Include="..\src\common\malloc.h" />
@ -183,6 +184,7 @@
<ClCompile Include="..\3rdparty\libconfig\strbuf.c" />
<ClCompile Include="..\3rdparty\mt19937ar\mt19937ar.c" />
<ClCompile Include="..\src\common\core.c" />
<ClCompile Include="..\src\common\conf.c" />
<ClCompile Include="..\src\common\db.c" />
<ClCompile Include="..\src\common\ers.c" />
<ClCompile Include="..\src\common\malloc.c" />
@ -217,4 +219,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>

View File

@ -4,6 +4,9 @@
<ClCompile Include="..\src\common\core.c">
<Filter>common</Filter>
</ClCompile>
<ClCompile Include="..\src\common\conf.c">
<Filter>common</Filter>
</ClCompile>
<ClCompile Include="..\src\common\db.c">
<Filter>common</Filter>
</ClCompile>
@ -114,6 +117,9 @@
<ClInclude Include="..\src\common\core.h">
<Filter>common</Filter>
</ClInclude>
<ClInclude Include="..\src\common\conf.h">
<Filter>common</Filter>
</ClInclude>
<ClInclude Include="..\src\common\db.h">
<Filter>common</Filter>
</ClInclude>
@ -246,4 +252,4 @@
<UniqueIdentifier>{9e8badd7-548f-4eb4-9e87-613e87e772ff}</UniqueIdentifier>
</Filter>
</ItemGroup>
</Project>
</Project>

View File

@ -153,6 +153,7 @@
<ClInclude Include="..\src\login\loginlog.h" />
<ClInclude Include="..\src\common\cbasetypes.h" />
<ClInclude Include="..\src\common\core.h" />
<ClInclude Include="..\src\common\conf.h" />
<ClInclude Include="..\src\common\db.h" />
<ClInclude Include="..\src\common\ers.h" />
<ClInclude Include="..\src\common\malloc.h" />
@ -185,6 +186,7 @@
<ClCompile Include="..\src\login\login.c" />
<ClCompile Include="..\src\login\loginlog_sql.c" />
<ClCompile Include="..\src\common\core.c" />
<ClCompile Include="..\src\common\conf.c" />
<ClCompile Include="..\src\common\db.c" />
<ClCompile Include="..\src\common\ers.c" />
<ClCompile Include="..\src\common\malloc.c" />
@ -204,4 +206,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>

View File

@ -16,6 +16,9 @@
<ClCompile Include="..\src\common\core.c">
<Filter>common</Filter>
</ClCompile>
<ClCompile Include="..\src\common\conf.c">
<Filter>common</Filter>
</ClCompile>
<ClCompile Include="..\src\common\db.c">
<Filter>common</Filter>
</ClCompile>
@ -102,6 +105,9 @@
<ClInclude Include="..\src\common\core.h">
<Filter>common</Filter>
</ClInclude>
<ClInclude Include="..\src\common\conf.h">
<Filter>common</Filter>
</ClInclude>
<ClInclude Include="..\src\common\db.h">
<Filter>common</Filter>
</ClInclude>
@ -198,4 +204,4 @@
<UniqueIdentifier>{779e8145-9bb2-4a88-9149-60586ab0bdd4}</UniqueIdentifier>
</Filter>
</ItemGroup>
</Project>
</Project>

View File

@ -405,7 +405,7 @@
<File
RelativePath="..\src\common\cli.c"
>
</File>
</File>
<File
RelativePath="..\src\common\msg_conf.h"
>
@ -413,7 +413,7 @@
<File
RelativePath="..\src\common\msg_conf.c"
>
</File>
</File>
</Filter>
<Filter