summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorshennetsind <ind@henn.et>2013-10-30 18:42:58 -0200
committershennetsind <ind@henn.et>2013-10-30 18:42:58 -0200
commitc159a3c4ffd414d7423b3504a282cce1111b7874 (patch)
tree0d7051a90bcd0b9ba229ff16d52a9dea0bbee743 /src
parent7fefefdde386f13f8fefa8db3ffe9ed140c8aa10 (diff)
downloadhercules-c159a3c4ffd414d7423b3504a282cce1111b7874.tar.gz
hercules-c159a3c4ffd414d7423b3504a282cce1111b7874.tar.bz2
hercules-c159a3c4ffd414d7423b3504a282cce1111b7874.tar.xz
hercules-c159a3c4ffd414d7423b3504a282cce1111b7874.zip
Account-wide Exp/Drop/Death Modifiers
Attempting to mimic the official as suggested in http://hercules.ws/board/topic/250-official-vip-system/ The variables can be read and modified thru scripting as well as sql, the patch introduces 3 new pc-arams 'ModExp','ModDrop' and 'ModDeath' for that purpose. The OnLogin modifier display is not the real deal though -- wasn't able to get it to output properly (though that might have been my client files failt) Up for review. Signed-off-by: shennetsind <ind@henn.et>
Diffstat (limited to 'src')
-rw-r--r--src/char/char.c20
-rw-r--r--src/common/mmo.h3
-rw-r--r--src/map/clif.c15
-rw-r--r--src/map/clif.h2
-rw-r--r--src/map/map.h3
-rw-r--r--src/map/mob.c6
-rw-r--r--src/map/pc.c296
7 files changed, 202 insertions, 143 deletions
diff --git a/src/char/char.c b/src/char/char.c
index 310163e3a..240acab53 100644
--- a/src/char/char.c
+++ b/src/char/char.c
@@ -499,12 +499,12 @@ int mmo_char_tosql(int char_id, struct mmo_charstatus* p)
strcat(save_status, " status");
}
- if( p->bank_vault != cp->bank_vault ) {
- if( SQL_ERROR == SQL->Query(sql_handle, "REPLACE INTO `%s` (`account_id`,`bank_vault`) VALUES ('%d','%d')",account_data_db,p->account_id,p->bank_vault) ) {
+ if( p->bank_vault != cp->bank_vault || p->mod_exp != cp->mod_exp || p->mod_drop != cp->mod_drop || p->mod_death != p->mod_death ) {
+ if( SQL_ERROR == SQL->Query(sql_handle, "REPLACE INTO `%s` (`account_id`,`bank_vault`,`base_exp`,`base_drop`,`base_death`) VALUES ('%d','%d','%d','%d','%d')",account_data_db,p->account_id,p->bank_vault,p->mod_exp,p->mod_drop,p->mod_death) ) {
Sql_ShowDebug(sql_handle);
errors++;
} else
- strcat(save_status, " bank");
+ strcat(save_status, " accdata");
}
//Values that will seldom change (to speed up saving)
@@ -1352,15 +1352,21 @@ int mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_everything
mercenary_owner_fromsql(char_id, p);
strcat(t_msg, " mercenary");
- //`account_data` (`account_id`,`bank_vault`)
- if( SQL_ERROR == SQL->StmtPrepare(stmt, "SELECT `bank_vault` FROM `%s` WHERE `account_id`=? LIMIT 1", account_data_db)
+ /* default */
+ p->mod_exp = p->mod_drop = p->mod_death = 100;
+
+ //`account_data` (`account_id`,`bank_vault`,`base_exp`,`base_drop`,`base_death`)
+ if( SQL_ERROR == SQL->StmtPrepare(stmt, "SELECT `bank_vault`,`base_exp`,`base_drop`,`base_death` FROM `%s` WHERE `account_id`=? LIMIT 1", account_data_db)
|| SQL_ERROR == SQL->StmtBindParam(stmt, 0, SQLDT_INT, &account_id, 0)
|| SQL_ERROR == SQL->StmtExecute(stmt)
- || SQL_ERROR == SQL->StmtBindColumn(stmt, 0, SQLDT_INT, &p->bank_vault, 0, NULL, NULL) )
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 0, SQLDT_INT, &p->bank_vault, 0, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 1, SQLDT_USHORT, &p->mod_exp, 0, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 2, SQLDT_USHORT, &p->mod_drop, 0, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 3, SQLDT_USHORT, &p->mod_death, 0, NULL, NULL) )
SqlStmt_ShowDebug(stmt);
if( SQL_SUCCESS == SQL->StmtNextRow(stmt) )
- strcat(t_msg, " bank");
+ strcat(t_msg, " accdata");
if (save_log) ShowInfo("Loaded char (%d - %s): %s\n", char_id, p->name, t_msg); //ok. all data load successfuly!
SQL->StmtFree(stmt);
diff --git a/src/common/mmo.h b/src/common/mmo.h
index 9281314dc..13748a787 100644
--- a/src/common/mmo.h
+++ b/src/common/mmo.h
@@ -414,6 +414,9 @@ struct mmo_charstatus {
unsigned short slotchange;
time_t delete_date;
+
+ /* `account_data` modifiers */
+ unsigned short mod_exp,mod_drop,mod_death;
};
typedef enum mail_status {
diff --git a/src/map/clif.c b/src/map/clif.c
index 957f75d99..a5e92b998 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -17798,6 +17798,19 @@ void clif_bank_withdraw(struct map_session_data *sd,enum e_BANKING_WITHDRAW_ACK
clif->send(&p,sizeof(p), &sd->bl, SELF);
}
+/* TODO: official response packet (tried 0x8cb/0x97b but the display was quite screwed up.) */
+/* currently mimicing */
+void clif_show_modifiers (struct map_session_data *sd) {
+
+ if( sd->status.mod_exp != 100 || sd->status.mod_drop != 100 || sd->status.mod_death != 100 ) {
+ char output[128];
+
+ snprintf(output,128,"Base EXP : %d%% | Base Drop: %d%% | Base Death Penalty: %d%%",
+ sd->status.mod_exp,sd->status.mod_drop,sd->status.mod_death);
+ clif->broadcast2(&sd->bl,output, strlen(output) + 1, 0xffbc90, 0x190, 12, 0, 0, SELF);
+ }
+
+}
/* */
unsigned short clif_decrypt_cmd( int cmd, struct map_session_data *sd ) {
@@ -18597,6 +18610,8 @@ void clif_defaults(void) {
/* Bank System [Yommy/Hercules] */
clif->bank_deposit = clif_bank_deposit;
clif->bank_withdraw = clif_bank_withdraw;
+ /* */
+ clif->show_modifiers = clif_show_modifiers;
/*------------------------
*- Parse Incoming Packet
*------------------------*/
diff --git a/src/map/clif.h b/src/map/clif.h
index cbe3fa857..d2ac9213a 100644
--- a/src/map/clif.h
+++ b/src/map/clif.h
@@ -1006,6 +1006,8 @@ struct clif_interface {
/* Bank System [Yommy/Hercules] */
void (*bank_deposit) (struct map_session_data *sd, enum e_BANKING_DEPOSIT_ACK reason);
void (*bank_withdraw) (struct map_session_data *sd,enum e_BANKING_WITHDRAW_ACK reason);
+ /* */
+ void (*show_modifiers) (struct map_session_data *sd);
/*------------------------
*- Parse Incoming Packet
*------------------------*/
diff --git a/src/map/map.h b/src/map/map.h
index 6b7d2a630..06c3829b1 100644
--- a/src/map/map.h
+++ b/src/map/map.h
@@ -360,6 +360,9 @@ enum _sp {
SP_KILLEDRID=122,
SP_SLOTCHANGE=123,
SP_CHARRENAME=124,
+ SP_MOD_EXP=125,
+ SP_MOD_DROP=126,
+ SP_MOD_DEATH=127,
// Mercenaries
SP_MERCFLEE=165, SP_MERCKILLS=189, SP_MERCFAITH=190,
diff --git a/src/map/mob.c b/src/map/mob.c
index 97f8ea6c1..778fc1dfa 100644
--- a/src/map/mob.c
+++ b/src/map/mob.c
@@ -2332,6 +2332,12 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) {
drop_rate = 1;
}
#endif
+ if( sd && sd->status.mod_drop != 100 ) {
+ drop_rate = drop_rate * sd->status.mod_drop / 100;
+ if( drop_rate < 1 )
+ drop_rate = 1;
+ }
+
// attempt to drop the item
if (rnd() % 10000 >= drop_rate)
continue;
diff --git a/src/map/pc.c b/src/map/pc.c
index 0244c6c84..564bc42d7 100644
--- a/src/map/pc.c
+++ b/src/map/pc.c
@@ -5827,6 +5827,9 @@ void pc_calcexp(struct map_session_data *sd, unsigned int *base_exp, unsigned in
if (sd->sc.data[SC_CASH_PLUSEXP])
bonus += sd->sc.data[SC_CASH_PLUSEXP]->val1;
+
+ if( sd->status.mod_exp != 100 )
+ bonus += sd->status.mod_exp - 100;
*base_exp = (unsigned int) cap_value(*base_exp + (double)*base_exp * bonus/100., 1, UINT_MAX);
@@ -6861,8 +6864,9 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) {
&& !map->list[sd->bl.m].flag.noexppenalty && !map_flag_gvg2(sd->bl.m)
&& !sd->sc.data[SC_BABY] && !sd->sc.data[SC_CASH_DEATHPENALTY]
) {
- unsigned int base_penalty =0;
+ unsigned int base_penalty = 0;
if (battle_config.death_penalty_base > 0) {
+
switch (battle_config.death_penalty_type) {
case 1:
base_penalty = (unsigned int) ((double)pc->nextbaseexp(sd) * (double)battle_config.death_penalty_base/10000);
@@ -6871,16 +6875,20 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) {
base_penalty = (unsigned int) ((double)sd->status.base_exp * (double)battle_config.death_penalty_base/10000);
break;
}
+
if(base_penalty) {
if (battle_config.pk_mode && src && src->type==BL_PC)
base_penalty*=2;
+ if( sd->status.mod_death != 100 )
+ base_penalty = base_penalty * sd->status.mod_death / 100;
sd->status.base_exp -= min(sd->status.base_exp, base_penalty);
clif->updatestatus(sd,SP_BASEEXP);
}
}
- if(battle_config.death_penalty_job > 0)
- {
+
+ if(battle_config.death_penalty_job > 0) {
base_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);
@@ -6889,15 +6897,18 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) {
base_penalty = (unsigned int) ((double)sd->status.job_exp * (double)battle_config.death_penalty_job/10000);
break;
}
+
if(base_penalty) {
if (battle_config.pk_mode && src && src->type==BL_PC)
base_penalty*=2;
+ if( sd->status.mod_death != 100 )
+ base_penalty = base_penalty * sd->status.mod_death / 100;
sd->status.job_exp -= min(sd->status.job_exp, base_penalty);
clif->updatestatus(sd,SP_JOBEXP);
}
}
- if(battle_config.zeny_penalty > 0 && !map->list[sd->bl.m].flag.nozenypenalty)
- {
+
+ if(battle_config.zeny_penalty > 0 && !map->list[sd->bl.m].flag.nozenypenalty) {
base_penalty = (unsigned int)((double)sd->status.zeny * (double)battle_config.zeny_penalty / 10000.);
if(base_penalty)
pc->payzeny(sd, base_penalty, LOG_TYPE_PICKDROP_PLAYER, NULL);
@@ -7049,6 +7060,9 @@ int pc_readparam(struct map_session_data* sd,int type)
case SP_KILLEDRID: val = sd->killedrid; break;
case SP_SLOTCHANGE: val = sd->status.slotchange; break;
case SP_CHARRENAME: val = sd->status.rename; break;
+ case SP_MOD_EXP: val = sd->status.mod_exp; break;
+ case SP_MOD_DROP: val = sd->status.mod_drop; break;
+ case SP_MOD_DEATH: val = sd->status.mod_death; break;
case SP_CRITICAL: val = sd->battle_status.cri/10; break;
case SP_ASPD: val = (2000-sd->battle_status.amotion)/10; break;
case SP_BASE_ATK: val = sd->battle_status.batk; break;
@@ -7166,139 +7180,148 @@ int pc_setparam(struct map_session_data *sd,int type,int val)
nullpo_ret(sd);
switch(type){
- case SP_BASELEVEL:
- if ((unsigned int)val > pc->maxbaselv(sd)) //Capping to max
- val = pc->maxbaselv(sd);
- if ((unsigned int)val > sd->status.base_level) {
- int stat=0;
- for (i = 0; i < (int)((unsigned int)val - sd->status.base_level); i++)
- stat += pc->gets_status_point(sd->status.base_level + i);
- sd->status.status_point += stat;
- }
- sd->status.base_level = (unsigned int)val;
- sd->status.base_exp = 0;
- // clif->updatestatus(sd, SP_BASELEVEL); // Gets updated at the bottom
- clif->updatestatus(sd, SP_NEXTBASEEXP);
- clif->updatestatus(sd, SP_STATUSPOINT);
- clif->updatestatus(sd, SP_BASEEXP);
- status_calc_pc(sd, 0);
- if(sd->status.party_id)
- {
- party->send_levelup(sd);
- }
- break;
- case SP_JOBLEVEL:
- if ((unsigned int)val >= sd->status.job_level) {
- if ((unsigned int)val > pc->maxjoblv(sd)) val = pc->maxjoblv(sd);
- sd->status.skill_point += val - sd->status.job_level;
- clif->updatestatus(sd, SP_SKILLPOINT);
- }
- sd->status.job_level = (unsigned int)val;
- sd->status.job_exp = 0;
- // clif->updatestatus(sd, SP_JOBLEVEL); // Gets updated at the bottom
- clif->updatestatus(sd, SP_NEXTJOBEXP);
- clif->updatestatus(sd, SP_JOBEXP);
- status_calc_pc(sd, 0);
- break;
- case SP_SKILLPOINT:
- sd->status.skill_point = val;
- break;
- case SP_STATUSPOINT:
- sd->status.status_point = val;
- break;
- case SP_ZENY:
- if( val < 0 )
- return 0;// can't set negative zeny
- logs->zeny(sd, LOG_TYPE_SCRIPT, sd, -(sd->status.zeny - cap_value(val, 0, MAX_ZENY)));
- sd->status.zeny = cap_value(val, 0, MAX_ZENY);
- break;
- case SP_BASEEXP:
- if(pc->nextbaseexp(sd) > 0) {
- sd->status.base_exp = val;
- pc->checkbaselevelup(sd);
- }
- break;
- case SP_JOBEXP:
- if(pc->nextjobexp(sd) > 0) {
- sd->status.job_exp = val;
- pc->checkjoblevelup(sd);
- }
- break;
- case SP_SEX:
- sd->status.sex = val ? SEX_MALE : SEX_FEMALE;
- break;
- case SP_WEIGHT:
- sd->weight = val;
- break;
- case SP_MAXWEIGHT:
- sd->max_weight = val;
- break;
- case SP_HP:
- sd->battle_status.hp = cap_value(val, 1, (int)sd->battle_status.max_hp);
- break;
- case SP_MAXHP:
- sd->battle_status.max_hp = cap_value(val, 1, battle_config.max_hp);
+ case SP_BASELEVEL:
+ if ((unsigned int)val > pc->maxbaselv(sd)) //Capping to max
+ val = pc->maxbaselv(sd);
+ if ((unsigned int)val > sd->status.base_level) {
+ int stat=0;
+ for (i = 0; i < (int)((unsigned int)val - sd->status.base_level); i++)
+ stat += pc->gets_status_point(sd->status.base_level + i);
+ sd->status.status_point += stat;
+ }
+ sd->status.base_level = (unsigned int)val;
+ sd->status.base_exp = 0;
+ // clif->updatestatus(sd, SP_BASELEVEL); // Gets updated at the bottom
+ clif->updatestatus(sd, SP_NEXTBASEEXP);
+ clif->updatestatus(sd, SP_STATUSPOINT);
+ clif->updatestatus(sd, SP_BASEEXP);
+ status_calc_pc(sd, 0);
+ if(sd->status.party_id)
+ {
+ party->send_levelup(sd);
+ }
+ break;
+ case SP_JOBLEVEL:
+ if ((unsigned int)val >= sd->status.job_level) {
+ if ((unsigned int)val > pc->maxjoblv(sd)) val = pc->maxjoblv(sd);
+ sd->status.skill_point += val - sd->status.job_level;
+ clif->updatestatus(sd, SP_SKILLPOINT);
+ }
+ sd->status.job_level = (unsigned int)val;
+ sd->status.job_exp = 0;
+ // clif->updatestatus(sd, SP_JOBLEVEL); // Gets updated at the bottom
+ clif->updatestatus(sd, SP_NEXTJOBEXP);
+ clif->updatestatus(sd, SP_JOBEXP);
+ status_calc_pc(sd, 0);
+ break;
+ case SP_SKILLPOINT:
+ sd->status.skill_point = val;
+ break;
+ case SP_STATUSPOINT:
+ sd->status.status_point = val;
+ break;
+ case SP_ZENY:
+ if( val < 0 )
+ return 0;// can't set negative zeny
+ logs->zeny(sd, LOG_TYPE_SCRIPT, sd, -(sd->status.zeny - cap_value(val, 0, MAX_ZENY)));
+ sd->status.zeny = cap_value(val, 0, MAX_ZENY);
+ break;
+ case SP_BASEEXP:
+ if(pc->nextbaseexp(sd) > 0) {
+ sd->status.base_exp = val;
+ pc->checkbaselevelup(sd);
+ }
+ break;
+ case SP_JOBEXP:
+ if(pc->nextjobexp(sd) > 0) {
+ sd->status.job_exp = val;
+ pc->checkjoblevelup(sd);
+ }
+ break;
+ case SP_SEX:
+ sd->status.sex = val ? SEX_MALE : SEX_FEMALE;
+ break;
+ case SP_WEIGHT:
+ sd->weight = val;
+ break;
+ case SP_MAXWEIGHT:
+ sd->max_weight = val;
+ break;
+ case SP_HP:
+ sd->battle_status.hp = cap_value(val, 1, (int)sd->battle_status.max_hp);
+ break;
+ case SP_MAXHP:
+ sd->battle_status.max_hp = cap_value(val, 1, battle_config.max_hp);
- if( sd->battle_status.max_hp < sd->battle_status.hp )
- {
- sd->battle_status.hp = sd->battle_status.max_hp;
- clif->updatestatus(sd, SP_HP);
- }
- break;
- case SP_SP:
- sd->battle_status.sp = cap_value(val, 0, (int)sd->battle_status.max_sp);
- break;
- case SP_MAXSP:
- sd->battle_status.max_sp = cap_value(val, 1, battle_config.max_sp);
+ if( sd->battle_status.max_hp < sd->battle_status.hp )
+ {
+ sd->battle_status.hp = sd->battle_status.max_hp;
+ clif->updatestatus(sd, SP_HP);
+ }
+ break;
+ case SP_SP:
+ sd->battle_status.sp = cap_value(val, 0, (int)sd->battle_status.max_sp);
+ break;
+ case SP_MAXSP:
+ sd->battle_status.max_sp = cap_value(val, 1, battle_config.max_sp);
- if( sd->battle_status.max_sp < sd->battle_status.sp )
- {
- sd->battle_status.sp = sd->battle_status.max_sp;
- clif->updatestatus(sd, SP_SP);
- }
- break;
- case SP_STR:
- sd->status.str = cap_value(val, 1, pc_maxparameter(sd));
- break;
- case SP_AGI:
- sd->status.agi = cap_value(val, 1, pc_maxparameter(sd));
- break;
- case SP_VIT:
- sd->status.vit = cap_value(val, 1, pc_maxparameter(sd));
- break;
- case SP_INT:
- sd->status.int_ = cap_value(val, 1, pc_maxparameter(sd));
- break;
- case SP_DEX:
- sd->status.dex = cap_value(val, 1, pc_maxparameter(sd));
- break;
- case SP_LUK:
- sd->status.luk = cap_value(val, 1, pc_maxparameter(sd));
- break;
- case SP_KARMA:
- sd->status.karma = val;
- break;
- case SP_MANNER:
- sd->status.manner = val;
- break;
- case SP_FAME:
- sd->status.fame = val;
- break;
- case SP_KILLERRID:
- sd->killerrid = val;
- return 1;
- case SP_KILLEDRID:
- sd->killedrid = val;
- return 1;
- case SP_SLOTCHANGE:
- sd->status.slotchange = val;
- return 1;
- case SP_CHARRENAME:
- sd->status.rename = val;
- return 1;
- default:
- ShowError("pc_setparam: Attempted to set unknown parameter '%d'.\n", type);
- return 0;
+ if( sd->battle_status.max_sp < sd->battle_status.sp )
+ {
+ sd->battle_status.sp = sd->battle_status.max_sp;
+ clif->updatestatus(sd, SP_SP);
+ }
+ break;
+ case SP_STR:
+ sd->status.str = cap_value(val, 1, pc_maxparameter(sd));
+ break;
+ case SP_AGI:
+ sd->status.agi = cap_value(val, 1, pc_maxparameter(sd));
+ break;
+ case SP_VIT:
+ sd->status.vit = cap_value(val, 1, pc_maxparameter(sd));
+ break;
+ case SP_INT:
+ sd->status.int_ = cap_value(val, 1, pc_maxparameter(sd));
+ break;
+ case SP_DEX:
+ sd->status.dex = cap_value(val, 1, pc_maxparameter(sd));
+ break;
+ case SP_LUK:
+ sd->status.luk = cap_value(val, 1, pc_maxparameter(sd));
+ break;
+ case SP_KARMA:
+ sd->status.karma = val;
+ break;
+ case SP_MANNER:
+ sd->status.manner = val;
+ break;
+ case SP_FAME:
+ sd->status.fame = val;
+ break;
+ case SP_KILLERRID:
+ sd->killerrid = val;
+ return 1;
+ case SP_KILLEDRID:
+ sd->killedrid = val;
+ return 1;
+ case SP_SLOTCHANGE:
+ sd->status.slotchange = val;
+ return 1;
+ case SP_CHARRENAME:
+ sd->status.rename = val;
+ return 1;
+ case SP_MOD_EXP:
+ sd->status.mod_exp = val;
+ return 1;
+ case SP_MOD_DROP:
+ sd->status.mod_drop = val;
+ return 1;
+ case SP_MOD_DEATH:
+ sd->status.mod_death = val;
+ return 1;
+ default:
+ ShowError("pc_setparam: Attempted to set unknown parameter '%d'.\n", type);
+ return 0;
}
clif->updatestatus(sd,type);
@@ -10140,6 +10163,7 @@ void pc_bank_withdraw(struct map_session_data *sd, int money) {
/* status change data arrived from char-server */
void pc_scdata_received(struct map_session_data *sd) {
pc->inventory_rentals(sd);
+ clif->show_modifiers(sd);
}
/*==========================================