Index: conf/msg_conf/map_msg.conf =================================================================== --- conf/msg_conf/map_msg.conf (revision 17307) +++ conf/msg_conf/map_msg.conf (working copy) @@ -629,7 +629,6 @@ 678: You are no longer the Guild Master. 679: You have become the Guild Master! 680: You have been recovered! -//681-899 free 681: Rune Knight T 682: Warlock T @@ -646,6 +645,10 @@ 693: Shadow Chaser T 694: Hanbok +695: Item %d has been removed from your inventory. +696: Item %d has been removed from your cart. +697: Item %d has been removed from your storage. +//698-899 free //------------------------------------ // More atcommands message Index: conf/battle/items.conf =================================================================== --- conf/battle/items.conf (revision 17307) +++ conf/battle/items.conf (working copy) @@ -51,12 +51,16 @@ // NOTE: Wedding Rings and Whips/Musical Instruments will check gender regardless of setting. ignore_items_gender: yes -// Item check? (Note 1) +// Item check? (Note 3) // On map change it will check for items not tagged as "available" and -// auto-delete them from inventory/cart. +// auto-delete them from inventory/cart. Items are auto-deleted from +// storage when the character data is saved. // NOTE: An item is not available if it was not loaded from the item_db or you // specify it as unavailable in db/item_avail.txt -item_check: no +// 1: Inventory +// 2: Cart +// 4: Storage +item_check: 0 // How much time must pass between item uses? // Only affects the delay between using items, prevents healing item abuse. Recommended ~500 ms Index: conf/battle/exp.conf =================================================================== --- conf/battle/exp.conf (revision 17307) +++ conf/battle/exp.conf (working copy) @@ -70,10 +70,10 @@ death_penalty_type: 1 // Base exp. penalty rate (Each 100 is 1% of their exp) -death_penalty_base: 100 +death_penalty_base: 300 // Job exp. penalty rate (Each 100 is 1% of their exp) -death_penalty_job: 100 +death_penalty_job: 300 // When a player dies (to another player), how much zeny should we penalize them with? // NOTE: It is a percentage of their zeny, so 100 = 1% Index: conf/char_athena.conf =================================================================== --- conf/char_athena.conf (revision 17307) +++ conf/char_athena.conf (working copy) @@ -143,7 +143,7 @@ // 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 +chars_per_account: 9 // Restrict character deletion by BaseLevel // 0: no restriction (players can delete characters of any level) Index: conf/groups.conf =================================================================== --- conf/groups.conf (revision 17307) +++ conf/groups.conf (working copy) @@ -97,6 +97,18 @@ }, { id: 1 + name: "VIP" + inherit: ( "Player" ) /* can do everything Players can */ + level: 0 + commands: { + /* no commands by default */ + } + permissions: { + /* no permissions by default */ + } +}, +{ + id: 2 name: "Super Player" inherit: ( "Player" ) /* can do everything Players can and more */ level: 0 @@ -136,7 +148,7 @@ } }, { - id: 2 + id: 3 name: "Support" inherit: ( "Super Player" ) level: 1 @@ -161,7 +173,7 @@ } }, { - id: 3 + id: 4 name: "Script Manager" inherit: ( "Support" ) level: 1 @@ -180,7 +192,7 @@ } }, { - id: 4 + id: 5 name: "Event Manager" inherit: ( "Support" ) level: 1 Index: sql-files/main.sql =================================================================== --- sql-files/main.sql (revision 17307) +++ sql-files/main.sql (working copy) @@ -442,6 +442,7 @@ `character_slots` tinyint(3) unsigned NOT NULL default '0', `pincode` varchar(4) NOT NULL DEFAULT '', `pincode_change` int(11) unsigned NOT NULL DEFAULT '0', + `vip_time` datetime NOT NULL default '0000-00-00 00:00:00', PRIMARY KEY (`account_id`), KEY `name` (`userid`) ) ENGINE=MyISAM AUTO_INCREMENT=2000000; Index: src/login/account_sql.c =================================================================== --- src/login/account_sql.c (revision 17307) +++ src/login/account_sql.c (working copy) @@ -7,6 +7,7 @@ #include "../common/sql.h" #include "../common/strlib.h" #include "../common/timer.h" +#include "../common/conf.h" //Inter_config #include "account.h" #include #include @@ -520,6 +521,28 @@ char* data; int i = 0; + if( Inter_Config.vip_sys.enable ) { + // Check for VIP time and set if date has not been reached. + if( SQL_SUCCESS == Sql_Query(sql_handle, + "UPDATE `%s` SET `group_id` = %d WHERE `group_id`< %d and `account_id` = %d AND `vip_time` >= NOW()", + db->account_db, Inter_Config.vip_sys.group,Inter_Config.vip_sys.group,account_id) //only update if group_id lower + ) { + // Add premium character slots. + Sql_Query(sql_handle, "UPDATE `%s` SET `character_slots` = %d WHERE `character_slots`< %d `account_id` = '%d'", db->account_db, Inter_Config.vip_sys.char_increase,Inter_Config.vip_sys.char_increase,account_id); + } + + // Check for VIP time and remove if date has been passed. + else if( SQL_SUCCESS == Sql_Query(sql_handle, + "UPDATE `%s` SET `group_id` = 0 WHERE `account_id` = %d AND `vip_time` != '0000-00-00 00:00:00' AND `vip_time` < NOW()", + db->account_db, account_id ) //@TODO return to previous group_id instead 0 ? + ) { + // Remove premium character slots. + // Setting to 0 will cause the char_server to force it to server default (char_athena.conf -> chars_per_account). + // Characters won't be deleted, they just won't be accessible. + Sql_Query(sql_handle, "UPDATE `%s` SET `character_slots` = 0 WHERE `account_id` = '%d'", db->account_db, account_id ); + } + } + // 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` FROM `%s` WHERE `account_id` = %d", Index: src/map/atcommand.c =================================================================== --- src/map/atcommand.c (revision 17307) +++ src/map/atcommand.c (working copy) @@ -7380,6 +7380,11 @@ nullpo_ret(sd); memset(buf, '\0', sizeof(buf)); + if( Inter_Config.vip_sys.enable && pc_get_vip(sd) ) { // Display EXP rate increase for VIP. + battle_config.base_exp_rate += Inter_Config.vip_sys.exp_increase; + battle_config.job_exp_rate += Inter_Config.vip_sys.exp_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.); clif_displaymessage(fd, buf); Index: src/map/skill.c =================================================================== --- src/map/skill.c (revision 17307) +++ src/map/skill.c (working copy) @@ -13147,7 +13147,7 @@ * 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] && ((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]); clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); @@ -13848,11 +13848,11 @@ continue; break; case AB_ADORAMUS: - if( itemid_isgemstone(skill_db[idx].itemid[i]) && skill_check_pc_partner(sd,skill_id,&skill_lv, 1, 2) ) + if( ( sd->special_state.no_gemstone != 2 ) && itemid_isgemstone(skill_db[idx].itemid[i]) && skill_check_pc_partner(sd,skill_id,&skill_lv, 1, 2) ) continue; break; case WL_COMET: - if( itemid_isgemstone(skill_db[idx].itemid[i]) && skill_check_pc_partner(sd,skill_id,&skill_lv, 1, 0) ) + if( ( sd->special_state.no_gemstone != 2 ) && itemid_isgemstone(skill_db[idx].itemid[i]) && skill_check_pc_partner(sd,skill_id,&skill_lv, 1, 0) ) continue; break; case GN_FIRE_EXPANSION: @@ -13875,8 +13875,11 @@ req.itemid[i] = skill_db[idx].itemid[i]; req.amount[i] = skill_db[idx].amount[i]; - if( itemid_isgemstone(req.itemid[i]) && skill_id != HW_GANBANTEIN ) - { + // Remove all Magic Stone required for all skills for VIP. + if( itemid_isgemstone(req.itemid[i]) && ( sd->special_state.no_gemstone == 2 ) ) { + req.itemid[i] = 0; + req.amount[i] = 0; + } else if( itemid_isgemstone(req.itemid[i]) && skill_id != HW_GANBANTEIN ) { if( sd->special_state.no_gemstone ) { //Make it substract 1 gem rather than skipping the cost. if( --req.amount[i] < 1 ) Index: src/map/pc.c =================================================================== --- src/map/pc.c (revision 17307) +++ src/map/pc.c (working copy) @@ -12,6 +12,7 @@ #include "../common/timer.h" #include "../common/utils.h" #include "../common/mmo.h" //NAME_LENGTH +#include "../common/conf.h" //Inter_config #include "atcommand.h" // get_atcommand_level() #include "battle.h" // battle_config @@ -38,6 +39,7 @@ #include "script.h" // script_config #include "skill.h" #include "status.h" // struct status_data +#include "storage.h" #include "pc.h" #include "pc_groups.h" #include "quest.h" @@ -1159,6 +1161,10 @@ sd->mission_count = pc_readglobalreg(sd,"TK_MISSION_COUNT"); } + // Magic Stone requirement avoidance for VIP. + if(Inter_Config.vip_sys.magic_stone && pc_get_vip(sd)) + sd->special_state.no_gemstone = 2; + //SG map and mob read [Komurka] for(i=0;istatus.account_id, sd->status.char_id); + pc_check_available_item(sd); // Check for invalid(ated) items in inventory/cart/storage. + pc_load_combo(sd); status_calc_pc(sd,1); @@ -2431,7 +2439,8 @@ break; case SP_NO_GEMSTONE: if(sd->state.lr_flag != 2) - sd->special_state.no_gemstone = 1; + if( 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] if(sd->state.lr_flag != 2) { @@ -5741,8 +5750,13 @@ (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]) { + // Increase Battle Manual EXP rate for VIP. + if( Inter_Config.vip_sys.bm_increase && pc_get_vip(sd) ) + bonus += sd->sc.data[SC_EXPBOOST]->val1 + ( sd->sc.data[SC_EXPBOOST]->val1 / Inter_Config.vip_sys.bm_increase ); + else + bonus += sd->sc.data[SC_EXPBOOST]->val1; + } *base_exp = (unsigned int) cap_value(*base_exp + (double)*base_exp * bonus/100., 1, UINT_MAX); @@ -6785,6 +6799,10 @@ && !map[sd->bl.m].flag.noexppenalty && !map_flag_gvg(sd->bl.m) && !sd->sc.data[SC_BABY] && !sd->sc.data[SC_LIFEINSURANCE]) { + if(Inter_Config.vip_sys.exp_penalty && pc_get_vip(sd) ) { // Decrease EXP penalty for VIP. + battle_config.death_penalty_base -= Inter_Config.vip_sys.exp_penalty; + battle_config.death_penalty_job -= Inter_Config.vip_sys.exp_penalty; + } unsigned int base_penalty =0; if (battle_config.death_penalty_base > 0) { switch (battle_config.death_penalty_type) { @@ -8859,54 +8877,86 @@ *------------------------------------------*/ int pc_checkitem(struct map_session_data *sd) { - int i,id,calc_flag = 0; + int i,calc_flag = 0; nullpo_ret(sd); if( sd->state.vending ) //Avoid reorganizing items when we are vending, as that leads to exploits (pointed out by End of Exam) return 0; - if( battle_config.item_check ) {// check for invalid(ated) items + for( i = 0; i < MAX_INVENTORY; i++) { + + if( sd->status.inventory[i].nameid == 0 ) + continue; + + if( !sd->status.inventory[i].equip ) + continue; + + if( sd->status.inventory[i].equip&~pc_equippoint(sd,i) ) { + pc_unequipitem(sd, i, 2); + calc_flag = 1; + continue; + } + + } + + if( calc_flag && sd->state.active ) { + pc_checkallowskill(sd); + status_calc_pc(sd,0); + } + + return 0; +} + +/*========================================== + * Checks for unavailable items and removes them. + *------------------------------------------*/ +int pc_check_available_item(struct map_session_data *sd) +{ + int i, id; + char output[256]; + + nullpo_ret(sd); + + if( battle_config.item_check&1 ) { // Check for invalid(ated) items in inventory. for( i = 0; i < MAX_INVENTORY; i++ ) { id = sd->status.inventory[i].nameid; if( id && !itemdb_available(id) ) { + sprintf(output, msg_txt(sd, 695), id); // Item %d has been removed from your inventory. + clif_displaymessage(sd->fd, output); ShowWarning("Removed invalid/disabled item id %d from inventory (amount=%d, char_id=%d).\n", id, sd->status.inventory[i].amount, sd->status.char_id); pc_delitem(sd, i, sd->status.inventory[i].amount, 0, 0, LOG_TYPE_OTHER); } } + } + if( battle_config.item_check&2 ) { // Check for invalid(ated) items in cart. for( i = 0; i < MAX_CART; i++ ) { id = sd->status.cart[i].nameid; if( id && !itemdb_available(id) ) { + sprintf(output, msg_txt(sd, 696), id); // Item %d has been removed from your cart. + clif_displaymessage(sd->fd, output); ShowWarning("Removed invalid/disabled item id %d from cart (amount=%d, char_id=%d).\n", id, sd->status.cart[i].amount, sd->status.char_id); pc_cart_delitem(sd, i, sd->status.cart[i].amount, 0, LOG_TYPE_OTHER); } } } - for( i = 0; i < MAX_INVENTORY; i++) { + if( battle_config.item_check&4 ) { // Check for invalid(ated) items in storage. + for( i = 0; i < MAX_STORAGE; i++ ) { + id = sd->status.storage.items[i].nameid; - if( sd->status.inventory[i].nameid == 0 ) - continue; - - if( !sd->status.inventory[i].equip ) - continue; - - if( sd->status.inventory[i].equip&~pc_equippoint(sd,i) ) { - pc_unequipitem(sd, i, 2); - calc_flag = 1; - continue; + if( id && !itemdb_available(id) ) { + sprintf(output, msg_txt(sd, 697), id); // Item %d has been removed from your storage. + clif_displaymessage(sd->fd, output); + ShowWarning("Removed invalid/disabled item id %d from storage (amount=%d, char_id=%d).\n", id, sd->status.storage.items[i].amount, sd->status.char_id); + storage_delitem(sd, i, sd->status.storage.items[i].amount); + } } - } - if( calc_flag && sd->state.active ) { - pc_checkallowskill(sd); - status_calc_pc(sd,0); - } - return 0; } Index: src/map/pc.h =================================================================== --- src/map/pc.h (revision 17307) +++ src/map/pc.h (working copy) @@ -178,7 +178,7 @@ 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; // 1: Mistress Card effect, 2: VIP effect unsigned int intravision : 1; // Maya Purple Card effect [DracoRPG] unsigned int perfect_hiding : 1; // [Valaris] unsigned int no_knockback : 1; @@ -669,6 +669,8 @@ ) #define pcdb_checkid(class_) pcdb_checkid_sub((unsigned int)class_) +#define pc_get_vip(sd) ( pc_get_group_id(sd) == Inter_Config.vip_sys.group ? 1 : 0 ) + // clientside display macros (values to the left/right of the "+") #ifdef RENEWAL #define pc_leftside_atk(sd) ((sd)->battle_status.batk) @@ -812,6 +814,7 @@ int pc_equipitem(struct map_session_data*,int,int); int pc_unequipitem(struct map_session_data*,int,int); int pc_checkitem(struct map_session_data*); +int pc_check_available_item(struct map_session_data *sd); int pc_useitem(struct map_session_data*,int); int pc_skillatk_bonus(struct map_session_data *sd, uint16 skill_id); Index: src/map/mob.c =================================================================== --- src/map/mob.c (revision 17307) +++ src/map/mob.c (working copy) @@ -12,6 +12,7 @@ #include "../common/strlib.h" #include "../common/utils.h" #include "../common/socket.h" +#include "../common/conf.h" //Inter_config #include "map.h" #include "path.h" @@ -2243,6 +2244,10 @@ zeny*=rnd()%250; } + // Increase EXP rate for VIP. + if( Inter_Config.vip_sys.exp_increase && ( sd && pc_get_vip(sd) ) ) + bonus += Inter_Config.vip_sys.exp_increase; + if (map[m].flag.nobaseexp || !md->db->base_exp) base_exp = 0; else @@ -2371,6 +2376,11 @@ drop_rate = 1; } #endif + + // Increase item drop rate for VIP. + if( Inter_Config.vip_sys.drop_increase && ( sd && pc_get_vip(sd) ) ) + drop_rate = max(drop_rate,cap_value((int)(0.5+drop_rate*Inter_Config.vip_sys.drop_increase/10000.),0,9000)); // now rig the drop rate to never be over 90% unless it is originally >90%. + // attempt to drop the item if (rnd() % 10000 >= drop_rate) continue; Index: src/map/clif.c =================================================================== --- src/map/clif.c (revision 17307) +++ src/map/clif.c (working copy) @@ -2418,6 +2418,7 @@ void clif_storagelist(struct map_session_data* sd, struct item* items, int items_length) { + static const int client_buf = 0x5000; struct item_data *id; int i,n,ne; unsigned char *buf; @@ -2469,27 +2470,33 @@ n++; } } - if( n ) + for (i = 0; i < n;) { + int nn = n - i < (client_buf - 4)/s ? n - i : (client_buf - 4)/s; + unsigned char *p = buf + i*s; + i += nn; #if PACKETVER < 5 - WBUFW(buf,0)=0xa5; + WBUFW(p,0)=0xa5; #elif PACKETVER < 20080102 - WBUFW(buf,0)=0x1f0; + WBUFW(p,0)=0x1f0; #else - WBUFW(buf,0)=0x2ea; + WBUFW(p,0)=0x2ea; #endif - WBUFW(buf,2)=4+n*s; - clif_send(buf, WBUFW(buf,2), &sd->bl, SELF); + WBUFW(p,2)=4+nn*s; + clif_send(p, WBUFW(p,2), &sd->bl, SELF); } - if( ne ) + for (i = 0; i < ne;) { + int nn = ne - i < (client_buf - 4)/cmd ? ne - i : (client_buf - 4)/cmd; + unsigned char *p = bufe + i*cmd; + i += nn; #if PACKETVER < 20071002 - WBUFW(bufe,0)=0xa6; + WBUFW(p,0)=0xa6; #else - WBUFW(bufe,0)=0x2d1; + WBUFW(p,0)=0x2d1; #endif - WBUFW(bufe,2)=4+ne*cmd; - clif_send(bufe, WBUFW(bufe,2), &sd->bl, SELF); + WBUFW(p,2)=4+nn*cmd; + clif_send(p, WBUFW(p,2), &sd->bl, SELF); } if( buf ) aFree(buf); @@ -14112,7 +14119,7 @@ return; } - if( (item = itemdb_exists(sd->status.inventory[idx].nameid)) != NULL && !(item->type == IT_ARMOR || item->type == IT_PETARMOR || item->type == IT_WEAPON || item->type == IT_CARD || item->type == IT_ETC) ) + if( (item = itemdb_exists(sd->status.inventory[idx].nameid)) != NULL && itemdb_available(sd->status.inventory[idx].nameid) && !(item->type == IT_ARMOR || item->type == IT_PETARMOR || item->type == IT_WEAPON || item->type == IT_CARD || item->type == IT_ETC) ) { // Consumable or pets are not allowed clif_Auction_setitem(sd->fd, idx, true); return; Index: src/map/itemdb.c =================================================================== --- src/map/itemdb.c (revision 17307) +++ src/map/itemdb.c (working copy) @@ -1422,6 +1422,7 @@ for( sd = (struct map_session_data*)mapit_first(iter); mapit_exists(iter); sd = (struct map_session_data*)mapit_next(iter) ) { memset(sd->item_delay, 0, sizeof(sd->item_delay)); // reset item delays pc_setinventorydata(sd); + pc_check_available_item(sd); // Check for invalid(ated) items in inventory/cart/storage. /* clear combo bonuses */ if( sd->combos.count ) { aFree(sd->combos.bonus); Index: src/map/mail.c =================================================================== --- src/map/mail.c (revision 17307) +++ src/map/mail.c (working copy) @@ -78,7 +78,7 @@ return 1; if( amount < 0 || amount > sd->status.inventory[idx].amount ) return 1; - if( !pc_can_give_items(sd) || sd->status.inventory[idx].expire_time || + if( !pc_can_give_items(sd) || !itemdb_available(sd->status.inventory[idx].nameid) || sd->status.inventory[idx].expire_time || !itemdb_canmail(&sd->status.inventory[idx],pc_get_group_level(sd)) ) return 1; Index: src/map/battle.c =================================================================== --- src/map/battle.c (revision 17307) +++ src/map/battle.c (working copy) @@ -5668,7 +5668,7 @@ { "max_heal_lv", &battle_config.max_heal_lv, 11, 1, INT_MAX, }, { "max_heal", &battle_config.max_heal, 9999, 0, INT_MAX, }, { "combo_delay_rate", &battle_config.combo_delay_rate, 100, 0, INT_MAX, }, - { "item_check", &battle_config.item_check, 0, 0, 1, }, + { "item_check", &battle_config.item_check, 0, 0, 7, }, { "item_use_interval", &battle_config.item_use_interval, 100, 0, INT_MAX, }, { "cashfood_use_interval", &battle_config.cashfood_use_interval, 60000, 0, INT_MAX, }, { "wedding_modifydisplay", &battle_config.wedding_modifydisplay, 0, 0, 1, }, Index: src/char/char.c =================================================================== --- src/char/char.c (revision 17307) +++ src/char/char.c (working copy) @@ -108,7 +108,7 @@ #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_per_account = 0; //Maximum chars per account [Sirius] int char_del_level = 0; //From which level u can delete character [Lupus] int char_del_delay = 86400; @@ -1563,12 +1563,10 @@ // 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) >= char_per_account ) + 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) ) @@ -2243,7 +2241,7 @@ 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 = char_per_account;/* cap to config */ 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); @@ -5053,9 +5051,8 @@ 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); + if(char_per_account <= 0 || 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] Index: src/common/core.c =================================================================== --- src/common/core.c (revision 17307) +++ src/common/core.c (working copy) @@ -5,6 +5,7 @@ #include "showmsg.h" #include "malloc.h" #include "core.h" +#include "conf.h" #ifndef MINICORE #include "db.h" #include "socket.h" @@ -355,5 +356,7 @@ malloc_final(); + inter_conf_read(); + return 0; } Index: src/common/mmo.h =================================================================== --- src/common/mmo.h (revision 17307) +++ src/common/mmo.h (working copy) @@ -72,7 +72,7 @@ #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 +#define MAX_CHARS 15 //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 Index: src/common/conf.c =================================================================== --- src/common/conf.c (revision 17307) +++ src/common/conf.c (working copy) @@ -3,6 +3,8 @@ #include "conf.h" #include "libconfig.h" +#include "utils.h" +#include "mmo.h" #include "../common/showmsg.h" // ShowError @@ -64,7 +66,7 @@ config_setting_set_format(set, src->format); } else if (CONFIG_TYPE_INT64 == config_setting_type(src)) { set = config_setting_set_int64_elem(parent, -1, config_setting_get_int64(src)); - config_setting_set_format(set, src->format); + config_setting_set_format(set, src->format); } else if (CONFIG_TYPE_FLOAT == config_setting_type(src)) { config_setting_set_float_elem(parent, -1, config_setting_get_float(src)); } else if (CONFIG_TYPE_STRING == config_setting_type(src)) { @@ -85,10 +87,10 @@ return; n = config_setting_length(src); - + for (i = 0; i < n; i++) { if (config_setting_is_group(src)) { - config_setting_copy_simple(newAgg, config_setting_get_elem(src, i)); + config_setting_copy_simple(newAgg, config_setting_get_elem(src, i)); } else { config_setting_copy_elem(newAgg, config_setting_get_elem(src, i)); } @@ -107,3 +109,54 @@ } return CONFIG_TRUE; } + +// +// Global configuration settings. +// +void inter_conf_read(void); + +void inter_conf_read(void){ + config_t inter_conf; + config_setting_t *sys = NULL; + const char *config_filename = "conf/inter_battle.conf"; + + if (conf_read_file(&inter_conf, config_filename)) + return; + + sys = config_lookup(&inter_conf, "vip_sys"); + if (sys != NULL) { //reading vip_sys part + config_setting_t *settings = config_setting_get_elem(sys, 0); + unsigned int enable; //:1 + unsigned int group; + unsigned int magic_stone; //:1 + unsigned int storage_increase; + unsigned int char_increase; + unsigned int exp_increase; + unsigned int exp_penalty; + unsigned int bm_increase; + unsigned int drop_increase; + + config_setting_lookup_bool(settings, "enable", &enable); + Inter_Config.vip_sys.enable = enable; + + if (enable) { + config_setting_lookup_int(settings, "group", &group); + config_setting_lookup_int(settings, "storage_increase", &storage_increase); + config_setting_lookup_int(settings, "char_increase", &char_increase); + config_setting_lookup_int(settings, "exp_increase", &exp_increase); + config_setting_lookup_int(settings, "exp_penalty", &exp_penalty); + config_setting_lookup_int(settings, "bm_increase", &bm_increase); + config_setting_lookup_int(settings, "drop_increase", &drop_increase); + config_setting_lookup_bool(settings, "magic_stone", &magic_stone); + } + + Inter_Config.vip_sys.group = cap_value(storage_increase,0,99); + Inter_Config.vip_sys.storage_increase = cap_value(storage_increase,0,1000); + Inter_Config.vip_sys.char_increase = cap_value(char_increase,0,MAX_CHARS); + Inter_Config.vip_sys.exp_increase = cap_value(exp_increase,0,INT_MAX); + Inter_Config.vip_sys.exp_penalty = cap_value(exp_penalty,0,INT_MAX); + Inter_Config.vip_sys.bm_increase = cap_value(bm_increase,0,INT_MAX); + Inter_Config.vip_sys.drop_increase = cap_value(drop_increase,0,INT_MAX); + Inter_Config.vip_sys.magic_stone = magic_stone; + } +} Index: src/common/conf.h =================================================================== --- src/common/conf.h (revision 17307) +++ src/common/conf.h (working copy) @@ -7,6 +7,22 @@ #include "../common/cbasetypes.h" #include "libconfig.h" +struct { + struct { + unsigned int enable : 1; + unsigned int group; + unsigned int storage_increase; + unsigned int char_increase; + unsigned int exp_increase; + unsigned int exp_penalty; + unsigned int bm_increase; + unsigned int drop_increase; + unsigned int magic_stone : 1; + } vip_sys; +} Inter_Config; + +void inter_conf_read(void); + int conf_read_file(config_t *config, const char *config_filename); int config_setting_copy(config_setting_t *parent, const config_setting_t *src);