Index: vcproj-10/login-server_sql.vcxproj
===================================================================
--- vcproj-10/login-server_sql.vcxproj (revision 17327)
+++ vcproj-10/login-server_sql.vcxproj (working copy)
@@ -138,6 +138,7 @@
+
@@ -172,6 +173,7 @@
+
@@ -200,4 +202,4 @@
-
\ No newline at end of file
+
Index: vcproj-10/char-server_sql.vcxproj
===================================================================
--- vcproj-10/char-server_sql.vcxproj (revision 17327)
+++ vcproj-10/char-server_sql.vcxproj (working copy)
@@ -138,6 +138,7 @@
+
@@ -179,6 +180,7 @@
+
@@ -214,4 +216,4 @@
-
\ No newline at end of file
+
Index: vcproj-10/login-server_sql.vcxproj.filters
===================================================================
--- vcproj-10/login-server_sql.vcxproj.filters (revision 17327)
+++ vcproj-10/login-server_sql.vcxproj.filters (working copy)
@@ -82,6 +82,11 @@
common
+
+
+
+ common
+
@@ -180,6 +185,11 @@
common
+
+
+
+ common
+
@@ -198,4 +208,4 @@
{779e8145-9bb2-4a88-9149-60586ab0bdd4}
-
\ No newline at end of file
+
Index: vcproj-10/char-server_sql.vcxproj.filters
===================================================================
--- vcproj-10/char-server_sql.vcxproj.filters (revision 17327)
+++ vcproj-10/char-server_sql.vcxproj.filters (working copy)
@@ -106,6 +106,11 @@
common
+
+
+
+ common
+
@@ -228,6 +233,11 @@
common
+
+
+
+ common
+
@@ -246,4 +256,4 @@
{9e8badd7-548f-4eb4-9e87-613e87e772ff}
-
\ No newline at end of file
+
Index: src/login/account_sql.c
===================================================================
--- src/login/account_sql.c (revision 17327)
+++ 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
@@ -518,8 +519,62 @@
{
Sql* sql_handle = db->accounts;
char* data;
- int i = 0;
+ int i = 0, acc_id = 0;
+ if( Inter_Config.vip_sys.enable ) {
+ ShowDebug("Reached login-server VIP system.\n");
+
+ ShowDebug("- Group ID: %d.\n", Inter_Config.vip_sys.group);
+ if( SQL_SUCCESS == Sql_Query(sql_handle, "SELECT `account_id` FROM `%s` WHERE `group_id` < %d AND `account_id` = %d AND `vip_time` >= NOW()", db->account_db, Inter_Config.vip_sys.group, account_id) ){
+ if( SQL_SUCCESS == Sql_NextRow(sql_handle) ){
+ Sql_GetData(sql_handle, 0, &data, NULL); acc_id = atoi(data);
+ ShowDebug("- Account ID: %d.\n", acc_id);
+ Sql_FreeResult(sql_handle);
+ }
+ }
+ else Sql_ShowDebug(sql_handle);
+
+ if( acc_id ){ // Adjust to VIP group and add premium character slots.
+ if( SQL_SUCCESS != Sql_Query(sql_handle, "UPDATE `%s` SET `group_id` = %d, `character_slots` = %d WHERE `character_slots` < %d AND `account_id` = %d", db->account_db, Inter_Config.vip_sys.group, Inter_Config.vip_sys.char_increase, Inter_Config.vip_sys.char_increase, account_id))
+ Sql_ShowDebug(sql_handle);
+ ShowDebug("- Increased character slots.");
+ acc_id = 0;
+ }
+
+ if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `account_id` FROM `%s` WHERE `account_id` = %d AND `vip_time` != '0000-00-00 00:00:00' AND `vip_time` < NOW()", db->account_db, account_id) ){
+ if( SQL_SUCCESS == Sql_NextRow(sql_handle) ){
+ Sql_GetData(sql_handle, 0, &data, NULL); acc_id = atoi(data);
+ Sql_FreeResult(sql_handle);
+ }
+ }
+ else Sql_ShowDebug(sql_handle);
+
+ if( acc_id ){ // Adjust to VIP group and add premium character slots.
+ Sql_Query(sql_handle, "UPDATE `%s` SET `group_id` = 0, `character_slots` = 0 WHERE `account_id` = %d", db->account_db, account_id);
+ ShowDebug("- Decreased character slots.");
+ }
+
+ // 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 is lower.
+// ) {
+ // Add premium character slots.
+// Sql_Query(sql_handle, "UPDATE `%s` SET `character_slots` = %d WHERE `character_slots` < %d AND `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 (MIN_CHARS).
+ // 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/skill.c
===================================================================
--- src/map/skill.c (revision 17327)
+++ src/map/skill.c (working copy)
@@ -13136,7 +13136,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]
&& 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]);
@@ -13857,11 +13857,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:
@@ -13884,7 +13884,10 @@
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] = req.amount[i] = 0;
+ else 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
Index: src/map/clif.c
===================================================================
--- src/map/clif.c (revision 17327)
+++ src/map/clif.c (working copy)
@@ -14098,7 +14098,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/atcommand.c
===================================================================
--- src/map/atcommand.c (revision 17327)
+++ src/map/atcommand.c (working copy)
@@ -7348,21 +7348,30 @@
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( ( Inter_Config.vip_sys.base_exp_increase || Inter_Config.vip_sys.job_exp_increase || Inter_Config.vip_sys.drop_increase ) && pc_get_vip(sd) ) {
+ base_exp_rate += Inter_Config.vip_sys.base_exp_increase;
+ job_exp_rate += Inter_Config.vip_sys.job_exp_increase;
+
+ item_rate += Inter_Config.vip_sys.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;
@@ -8083,7 +8092,7 @@
{
location = "storage";
items = sd->status.storage.items;
- size = MAX_STORAGE;
+ size = sd->storage_size;
}
else
if( strcmp(command+1, "cartlist") == 0 )
Index: src/map/mail.c
===================================================================
--- src/map/mail.c (revision 17327)
+++ 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/itemdb.c
===================================================================
--- src/map/itemdb.c (revision 17327)
+++ src/map/itemdb.c (working copy)
@@ -1448,6 +1448,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/pc.c
===================================================================
--- src/map/pc.c (revision 17327)
+++ 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"
@@ -1082,6 +1084,18 @@
clif_changemap(sd,sd->mapindex,sd->bl.x,sd->bl.y);
}
+ // Increase storage size for VIP.
+ if( pc_get_vip(sd) ) {
+ int vip_size = Inter_Config.vip_sys.storage_increase;
+
+ if( vip_size + MIN_STORAGE > MAX_STORAGE ) {
+ ShowError("pc_authok: 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;
+ } else
+ sd->storage_size = vip_size + MIN_STORAGE;
+ } else
+ sd->storage_size = MIN_STORAGE;
+
/**
* Check if player have any cool downs on
**/
@@ -1159,6 +1173,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 +2451,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) {
@@ -5745,8 +5766,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);
@@ -6804,39 +6830,38 @@
&& !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;
+ if( ( Inter_Config.vip_sys.base_exp_penalty || Inter_Config.vip_sys.job_exp_penalty ) && pc_get_vip(sd) ) { // Decrease EXP penalty for VIP.
+ base_penalty -= Inter_Config.vip_sys.base_exp_penalty;
+ job_penalty -= Inter_Config.vip_sys.job_exp_penalty;
+ }
+ 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);
+ base_penalty = (unsigned int) ((double)pc_nextbaseexp(sd) * (double)base_penalty/10000);
break;
case 2:
- base_penalty = (unsigned int) ((double)sd->status.base_exp * (double)battle_config.death_penalty_base/10000);
+ base_penalty = (unsigned int) ((double)sd->status.base_exp * (double)base_penalty/10000);
break;
}
- if(base_penalty) {
- 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.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);
+ job_penalty = (unsigned int) ((double)pc_nextjobexp(sd) * (double)job_penalty/10000);
break;
case 2:
- base_penalty = (unsigned int) ((double)sd->status.job_exp * (double)battle_config.death_penalty_job/10000);
+ job_penalty = (unsigned int) ((double)sd->status.job_exp * (double)job_penalty/10000);
break;
}
- if(base_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);
- clif_updatestatus(sd,SP_JOBEXP);
- }
+ if (battle_config.pk_mode && src && src->type==BL_PC)
+ job_penalty*=2;
+ sd->status.job_exp -= min(sd->status.job_exp, job_penalty);
+ clif_updatestatus(sd,SP_JOBEXP);
}
if(battle_config.zeny_penalty > 0 && !map[sd->bl.m].flag.nozenypenalty) {
base_penalty = (unsigned int)((double)sd->status.zeny * (double)battle_config.zeny_penalty / 10000.);
@@ -8878,54 +8903,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 < sd->storage_size; 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 17327)
+++ 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;
@@ -515,6 +515,9 @@
const char* delunit_prevfile;
int delunit_prevline;
+ // Holds player storage size (VIP system).
+ int storage_size;
+
};
//Update this max as necessary. 55 is the value needed for Super Baby currently
@@ -669,6 +672,8 @@
)
#define pcdb_checkid(class_) pcdb_checkid_sub((unsigned int)class_)
+#define pc_get_vip(sd) ( Inter_Config.vip_sys.group && ( 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)
@@ -813,6 +818,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/storage.c
===================================================================
--- src/map/storage.c (revision 17327)
+++ src/map/storage.c (working copy)
@@ -107,7 +107,7 @@
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;
}
@@ -156,7 +156,7 @@
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
@@ -170,8 +170,8 @@
}
// 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
@@ -179,7 +179,7 @@
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;
}
@@ -197,7 +197,7 @@
{
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;
@@ -214,7 +214,7 @@
{
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 )
@@ -243,7 +243,7 @@
{
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 )
@@ -271,7 +271,7 @@
{
nullpo_ret(sd);
- if( sd->status.storage.storage_amount > MAX_STORAGE )
+ if( sd->status.storage.storage_amount > sd->storage_size )
return 0; // storage full / storage closed
if( index < 0 || index >= MAX_CART )
@@ -300,7 +300,7 @@
{
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 )
Index: src/map/battle.c
===================================================================
--- src/map/battle.c (revision 17327)
+++ src/map/battle.c (working copy)
@@ -5669,7 +5669,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/map/mob.c
===================================================================
--- src/map/mob.c (revision 17327)
+++ 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"
@@ -2245,13 +2246,23 @@
if (map[m].flag.nobaseexp || !md->db->base_exp)
base_exp = 0;
- else
+ else {
+ // Increase base EXP rate for VIP.
+ if( Inter_Config.vip_sys.base_exp_increase && ( sd && pc_get_vip(sd) ) )
+ bonus += Inter_Config.vip_sys.base_exp_increase;
+
base_exp = (unsigned int)cap_value(md->db->base_exp * per * bonus/100. * map[m].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
+ else {
+ // Increase job EXP rate for VIP.
+ if( Inter_Config.vip_sys.job_exp_increase && ( sd && pc_get_vip(sd) ) )
+ bonus += Inter_Config.vip_sys.job_exp_increase;
+
job_exp = (unsigned int)cap_value(md->db->job_exp * per * bonus/100. * map[m].jexp/100., 1, UINT_MAX);
+ }
if ( ( temp = tmpsd[i]->status.party_id)>0 ) {
int j;
@@ -2371,6 +2382,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 += (int)(0.5+drop_rate*Inter_Config.vip_sys.drop_increase/100.);
+
// attempt to drop the item
if (rnd() % 10000 >= drop_rate)
continue;
Index: src/char/char.c
===================================================================
--- src/char/char.c (revision 17327)
+++ src/char/char.c (working copy)
@@ -108,7 +108,6 @@
#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;
@@ -1408,8 +1407,6 @@
{
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
@@ -1548,9 +1545,9 @@
//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
@@ -1561,14 +1558,11 @@
return -2; // invalid input
#endif
-
// 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) >= MAX_CHARS )
+ 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) )
@@ -2242,7 +2236,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 = 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);
@@ -5044,13 +5038,6 @@
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) {
Index: src/common/core.c
===================================================================
--- src/common/core.c (revision 17327)
+++ 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"
@@ -334,6 +335,8 @@
timer_init();
socket_init();
+ inter_conf_read();
+
do_init(argc,argv);
{// Main runtime cycle
Index: src/common/mmo.h
===================================================================
--- src/common/mmo.h (revision 17327)
+++ src/common/mmo.h (working copy)
@@ -71,8 +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
+#define MIN_CHARS 9 // Default number of characters per account.
+#define MAX_CHARS 15 // 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.
//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 +90,8 @@
#define DEFAULT_WALK_SPEED 150
#define MIN_WALK_SPEED 0
#define MAX_WALK_SPEED 1000
-#define MAX_STORAGE 600
+#define MIN_STORAGE 300 // Default number of storage slots.
+#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]
Index: src/common/conf.c
===================================================================
--- src/common/conf.c (revision 17327)
+++ 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,60 @@
}
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);
+ int enable; //:1
+ int group;
+ int magic_stone; //:1
+ int storage_increase;
+ int char_increase;
+ int base_exp_increase;
+ int job_exp_increase;
+ int base_exp_penalty;
+ int job_exp_penalty;
+ int bm_increase;
+ 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, "base_exp_increase", &base_exp_increase);
+ config_setting_lookup_int(settings, "job_exp_increase", &job_exp_increase);
+ config_setting_lookup_int(settings, "base_exp_penalty", &base_exp_penalty);
+ config_setting_lookup_int(settings, "job_exp_penalty", &job_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(group,0,99);
+ Inter_Config.vip_sys.storage_increase = cap_value(storage_increase,0,MAX_STORAGE-MIN_STORAGE);
+ Inter_Config.vip_sys.char_increase = cap_value(char_increase,0,MAX_CHARS-MIN_CHARS);
+ Inter_Config.vip_sys.base_exp_increase = cap_value(base_exp_increase,0,INT_MAX);
+ Inter_Config.vip_sys.job_exp_increase = cap_value(job_exp_increase,0,INT_MAX);
+ Inter_Config.vip_sys.base_exp_penalty = cap_value(base_exp_penalty,0,INT_MAX);
+ Inter_Config.vip_sys.job_exp_penalty = cap_value(job_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 17327)
+++ src/common/conf.h (working copy)
@@ -7,6 +7,24 @@
#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 base_exp_increase;
+ unsigned int job_exp_increase;
+ unsigned int base_exp_penalty;
+ unsigned int job_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);
Index: conf/msg_conf/map_msg.conf
===================================================================
--- conf/msg_conf/map_msg.conf (revision 17327)
+++ conf/msg_conf/map_msg.conf (working copy)
@@ -635,7 +635,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
@@ -652,6 +651,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/groups.conf
===================================================================
--- conf/groups.conf (revision 17327)
+++ 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: conf/battle/exp.conf
===================================================================
--- conf/battle/exp.conf (revision 17327)
+++ 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/battle/items.conf
===================================================================
--- conf/battle/items.conf (revision 17327)
+++ 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/char_athena.conf
===================================================================
--- conf/char_athena.conf (revision 17327)
+++ conf/char_athena.conf (working copy)
@@ -140,11 +140,6 @@
// 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
Index: sql-files/main.sql
===================================================================
--- sql-files/main.sql (revision 17327)
+++ 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;