Converted penalty db to YAML (#5562)
Fixes #5463 Added penalty for MVP exp and MVP drops Removed penalty support for monster classes Thanks to @attackjom and @aleos89
This commit is contained in:
parent
c349c82f60
commit
81e7d8ef89
@ -1,14 +0,0 @@
|
||||
// Experience & Drop Rate Modifier Database
|
||||
//
|
||||
// Structure of Database:
|
||||
// Type,Class,Level difference,Rate
|
||||
//
|
||||
// TYPE:
|
||||
// 1=experience, 2=item drop
|
||||
// CLASS:
|
||||
// 0=Normal monsters, 1=Boss monsters, 2=Guardians
|
||||
//
|
||||
// Note: RENEWAL_DROP and/or RENEWAL_EXP must be enabled.
|
||||
|
||||
// EXP modifiers due to level difference
|
||||
|
33
db/import-tmpl/level_penalty.yml
Normal file
33
db/import-tmpl/level_penalty.yml
Normal file
@ -0,0 +1,33 @@
|
||||
# This file is a part of rAthena.
|
||||
# Copyright(C) 2019 rAthena Development Team
|
||||
# https://rathena.org - https://github.com/rathena
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
###########################################################################
|
||||
# Level Penalty Database
|
||||
###########################################################################
|
||||
#
|
||||
# Level Penalty Settings
|
||||
#
|
||||
###########################################################################
|
||||
# - Type: Type of Penalty (Exp, Drop, Mvp_Exp, Mvp_Drop)
|
||||
# LevelDifferences: List of level difference between player and monster
|
||||
# - Difference: Level difference between player and monster
|
||||
# Rate: Rate applied to original exp or drop rate (0-10000)
|
||||
###########################################################################
|
||||
|
||||
Header:
|
||||
Type: PENALTY_DB
|
||||
Version: 1
|
39
db/level_penalty.yml
Normal file
39
db/level_penalty.yml
Normal file
@ -0,0 +1,39 @@
|
||||
# This file is a part of rAthena.
|
||||
# Copyright(C) 2019 rAthena Development Team
|
||||
# https://rathena.org - https://github.com/rathena
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
###########################################################################
|
||||
# Level Penalty Database
|
||||
###########################################################################
|
||||
#
|
||||
# Level Penalty Settings
|
||||
#
|
||||
###########################################################################
|
||||
# - Type: Type of Penalty (Exp, Drop, Mvp_Exp, Mvp_Drop)
|
||||
# LevelDifferences: List of level difference between player and monster
|
||||
# - Difference: Level difference between player and monster
|
||||
# Rate: Rate applied to original exp or drop rate (0-10000)
|
||||
###########################################################################
|
||||
|
||||
Header:
|
||||
Type: PENALTY_DB
|
||||
Version: 1
|
||||
|
||||
Footer:
|
||||
Imports:
|
||||
- Path: db/re/level_penalty.yml
|
||||
Mode: Renewal
|
||||
- Path: db/import/level_penalty.yml
|
@ -1,60 +0,0 @@
|
||||
// Experience & Drop Rate Modifier Database
|
||||
//
|
||||
// Structure of Database:
|
||||
// Type,Class,Level difference,Rate
|
||||
//
|
||||
// TYPE:
|
||||
// 1=experience, 2=item drop
|
||||
// CLASS:
|
||||
// 0=Normal monsters, 1=Boss monsters, 2=Guardians
|
||||
//
|
||||
// Note: RENEWAL_DROP and/or RENEWAL_EXP must be enabled.
|
||||
|
||||
// EXP modifiers due to level difference
|
||||
1,CLASS_NORMAL,16,40
|
||||
1,CLASS_NORMAL,15,115
|
||||
1,CLASS_NORMAL,14,120
|
||||
1,CLASS_NORMAL,13,125
|
||||
1,CLASS_NORMAL,12,130
|
||||
1,CLASS_NORMAL,11,135
|
||||
1,CLASS_NORMAL,10,140
|
||||
1,CLASS_NORMAL,9,135
|
||||
1,CLASS_NORMAL,8,130
|
||||
1,CLASS_NORMAL,7,125
|
||||
1,CLASS_NORMAL,6,120
|
||||
1,CLASS_NORMAL,5,115
|
||||
1,CLASS_NORMAL,4,110
|
||||
1,CLASS_NORMAL,3,105
|
||||
1,CLASS_NORMAL,0,100
|
||||
1,CLASS_NORMAL,-1,100
|
||||
1,CLASS_NORMAL,-6,95
|
||||
1,CLASS_NORMAL,-11,90
|
||||
1,CLASS_NORMAL,-16,85
|
||||
1,CLASS_NORMAL,-21,60
|
||||
1,CLASS_NORMAL,-26,35
|
||||
1,CLASS_NORMAL,-31,10
|
||||
|
||||
// Boss Type
|
||||
1,CLASS_BOSS,0,100
|
||||
|
||||
// Guardian Type
|
||||
1,CLASS_GUARDIAN,0,100
|
||||
|
||||
// Drop rate modifiers due to level difference
|
||||
2,CLASS_NORMAL,16,50
|
||||
2,CLASS_NORMAL,13,60
|
||||
2,CLASS_NORMAL,10,70
|
||||
2,CLASS_NORMAL,7,80
|
||||
2,CLASS_NORMAL,4,90
|
||||
2,CLASS_NORMAL,0,100
|
||||
2,CLASS_NORMAL,-4,90
|
||||
2,CLASS_NORMAL,-7,80
|
||||
2,CLASS_NORMAL,-10,70
|
||||
2,CLASS_NORMAL,-13,60
|
||||
2,CLASS_NORMAL,-16,50
|
||||
|
||||
// Boss Type
|
||||
2,CLASS_BOSS,0,100
|
||||
|
||||
// Guardian Type
|
||||
2,CLASS_GUARDIAN,0,100
|
99
db/re/level_penalty.yml
Normal file
99
db/re/level_penalty.yml
Normal file
@ -0,0 +1,99 @@
|
||||
# This file is a part of rAthena.
|
||||
# Copyright(C) 2019 rAthena Development Team
|
||||
# https://rathena.org - https://github.com/rathena
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
###########################################################################
|
||||
# Level Penalty Database
|
||||
###########################################################################
|
||||
#
|
||||
# Level Penalty Settings
|
||||
#
|
||||
###########################################################################
|
||||
# - Type: Type of Penalty (Exp, Drop, Mvp_Exp, Mvp_Drop)
|
||||
# LevelDifferences: List of level difference between player and monster
|
||||
# - Difference: Level difference between player and monster
|
||||
# Rate: Rate applied to original exp or drop rate (0-10000)
|
||||
###########################################################################
|
||||
|
||||
Header:
|
||||
Type: PENALTY_DB
|
||||
Version: 1
|
||||
|
||||
Body:
|
||||
- Type: Exp
|
||||
LevelDifferences:
|
||||
- Difference: 16
|
||||
Rate: 40
|
||||
- Difference: 15
|
||||
Rate: 115
|
||||
- Difference: 14
|
||||
Rate: 120
|
||||
- Difference: 13
|
||||
Rate: 125
|
||||
- Difference: 12
|
||||
Rate: 130
|
||||
- Difference: 11
|
||||
Rate: 135
|
||||
- Difference: 10
|
||||
Rate: 140
|
||||
- Difference: 9
|
||||
Rate: 135
|
||||
- Difference: 8
|
||||
Rate: 130
|
||||
- Difference: 7
|
||||
Rate: 125
|
||||
- Difference: 6
|
||||
Rate: 120
|
||||
- Difference: 5
|
||||
Rate: 115
|
||||
- Difference: 4
|
||||
Rate: 110
|
||||
- Difference: 3
|
||||
Rate: 105
|
||||
- Difference: -6
|
||||
Rate: 95
|
||||
- Difference: -11
|
||||
Rate: 90
|
||||
- Difference: -16
|
||||
Rate: 85
|
||||
- Difference: -21
|
||||
Rate: 60
|
||||
- Difference: -26
|
||||
Rate: 35
|
||||
- Difference: -31
|
||||
Rate: 10
|
||||
- Type: Drop
|
||||
LevelDifferences:
|
||||
- Difference: 16
|
||||
Rate: 50
|
||||
- Difference: 13
|
||||
Rate: 60
|
||||
- Difference: 10
|
||||
Rate: 70
|
||||
- Difference: 7
|
||||
Rate: 80
|
||||
- Difference: 4
|
||||
Rate: 90
|
||||
- Difference: -4
|
||||
Rate: 90
|
||||
- Difference: -7
|
||||
Rate: 80
|
||||
- Difference: -10
|
||||
Rate: 70
|
||||
- Difference: -13
|
||||
Rate: 60
|
||||
- Difference: -16
|
||||
Rate: 50
|
12
doc/yaml/db/level_penalty.yml
Normal file
12
doc/yaml/db/level_penalty.yml
Normal file
@ -0,0 +1,12 @@
|
||||
###########################################################################
|
||||
# Level Penalty Database
|
||||
###########################################################################
|
||||
#
|
||||
# Level Penalty Settings
|
||||
#
|
||||
###########################################################################
|
||||
# - Type: Type of Penalty (Exp, Drop, Mvp_Exp, Mvp_Drop)
|
||||
# LevelDifferences: List of level difference between player and monster
|
||||
# - Difference: Level difference between player and monster
|
||||
# Rate: Rate applied to original exp or drop rate (0-10000)
|
||||
###########################################################################
|
@ -7389,8 +7389,10 @@ ACMD_FUNC(mobinfo)
|
||||
}
|
||||
#ifdef RENEWAL_EXP
|
||||
if( battle_config.atcommand_mobinfo_type ) {
|
||||
base_exp = base_exp * pc_level_penalty_mod(mob->lv - sd->status.base_level, mob->status.class_, mob->status.mode, 1) / 100;
|
||||
job_exp = job_exp * pc_level_penalty_mod(mob->lv - sd->status.base_level, mob->status.class_, mob->status.mode, 1) / 100;
|
||||
int penalty = pc_level_penalty_mod( sd, PENALTY_EXP, mob );
|
||||
|
||||
base_exp = base_exp * penalty / 100;
|
||||
job_exp = job_exp * penalty / 100;
|
||||
}
|
||||
#endif
|
||||
// stats
|
||||
@ -7415,6 +7417,10 @@ ACMD_FUNC(mobinfo)
|
||||
clif_displaymessage(fd, msg_txt(sd,1245)); // Drops:
|
||||
strcpy(atcmd_output, " ");
|
||||
j = 0;
|
||||
#ifdef RENEWAL_DROP
|
||||
int penalty = pc_level_penalty_mod( sd, PENALTY_DROP, mob );
|
||||
#endif
|
||||
|
||||
for (i = 0; i < MAX_MOB_DROP_TOTAL; i++) {
|
||||
int droprate;
|
||||
if (mob->dropitem[i].nameid == 0 || mob->dropitem[i].rate < 1 || (item_data = itemdb_exists(mob->dropitem[i].nameid)) == NULL)
|
||||
@ -7423,7 +7429,7 @@ ACMD_FUNC(mobinfo)
|
||||
|
||||
#ifdef RENEWAL_DROP
|
||||
if( battle_config.atcommand_mobinfo_type ) {
|
||||
droprate = droprate * pc_level_penalty_mod(mob->lv - sd->status.base_level, mob->status.class_, mob->status.mode, 2) / 100;
|
||||
droprate = droprate * penalty / 100;
|
||||
if (droprate <= 0 && !battle_config.drop_rate0item)
|
||||
droprate = 1;
|
||||
}
|
||||
@ -7962,7 +7968,7 @@ ACMD_FUNC(whodrops)
|
||||
|
||||
#ifdef RENEWAL_DROP
|
||||
if( battle_config.atcommand_mobinfo_type )
|
||||
dropchance = dropchance * pc_level_penalty_mod(mob_db(item_data->mob[j].id)->lv - sd->status.base_level, mob_db(item_data->mob[j].id)->status.class_, mob_db(item_data->mob[j].id)->status.mode, 2) / 100;
|
||||
dropchance = dropchance * pc_level_penalty_mod( sd, PENALTY_DROP, mob_db( item_data->mob[j].id ) ) / 100;
|
||||
#endif
|
||||
if (pc_isvip(sd)) // Display item rate increase for VIP
|
||||
dropchance += (dropchance * battle_config.vip_drop_increase) / 100;
|
||||
|
@ -330,7 +330,7 @@
|
||||
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\job_exp.txt" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\job_exp.txt')" />
|
||||
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\job_noenter_map.txt" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\job_noenter_map.txt')" />
|
||||
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\job_param_db.txt" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\job_param_db.txt')" />
|
||||
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\level_penalty.txt" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\level_penalty.txt')" />
|
||||
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\level_penalty.yml" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\level_penalty.yml')" />
|
||||
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\magicmushroom_db.yml" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\magicmushroom_db.yml')" />
|
||||
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\map_cache.dat" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\map_cache.dat')" />
|
||||
<Copy SourceFiles="$(SolutionDir)db\import-tmpl\map_index.txt" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\map_index.txt')" />
|
||||
|
@ -2713,7 +2713,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
|
||||
if(base_exp || job_exp) {
|
||||
if( md->dmglog[i].flag != MDLF_PET || battle_config.pet_attack_exp_to_master ) {
|
||||
#ifdef RENEWAL_EXP
|
||||
int rate = pc_level_penalty_mod(md->level - tmpsd[i]->status.base_level, md->status.class_, md->status.mode, 1);
|
||||
int rate = pc_level_penalty_mod( tmpsd[i], PENALTY_EXP, nullptr, md );
|
||||
if (rate != 100) {
|
||||
if (base_exp)
|
||||
base_exp = (unsigned int)cap_value(apply_rate(base_exp, rate), 1, UINT_MAX);
|
||||
@ -2748,10 +2748,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
|
||||
struct item_data* it = NULL;
|
||||
int drop_rate;
|
||||
#ifdef RENEWAL_DROP
|
||||
int drop_modifier = mvp_sd ? pc_level_penalty_mod(md->level - mvp_sd->status.base_level, md->status.class_, md->status.mode, 2) :
|
||||
second_sd ? pc_level_penalty_mod(md->level - second_sd->status.base_level, md->status.class_, md->status.mode, 2):
|
||||
third_sd ? pc_level_penalty_mod(md->level - third_sd->status.base_level, md->status.class_, md->status.mode, 2) :
|
||||
100; // No player was attached, we don't use any modifier (100 = rates are not touched)
|
||||
int drop_modifier = pc_level_penalty_mod( mvp_sd != nullptr ? mvp_sd : second_sd != nullptr ? second_sd : third_sd, PENALTY_DROP, nullptr, md );
|
||||
#endif
|
||||
dlist->m = md->bl.m;
|
||||
dlist->x = md->bl.x;
|
||||
@ -2931,6 +2928,13 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
|
||||
exp =1;
|
||||
else {
|
||||
exp = md->db->mexp;
|
||||
|
||||
#if defined(RENEWAL_EXP)
|
||||
int penalty = pc_level_penalty_mod( mvp_sd, PENALTY_MVP_EXP, nullptr, md );
|
||||
|
||||
exp = cap_value( apply_rate( exp, penalty ), 0, MAX_EXP );
|
||||
#endif
|
||||
|
||||
if (count > 1)
|
||||
exp += exp*(battle_config.exp_bonus_attacker*(count-1))/100.; //[Gengar]
|
||||
}
|
||||
@ -2968,6 +2972,10 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(RENEWAL_DROP)
|
||||
int penalty = pc_level_penalty_mod( mvp_sd, PENALTY_MVP_DROP, nullptr, md );
|
||||
#endif
|
||||
|
||||
for(i = 0; i < MAX_MVP_DROP_TOTAL; i++) {
|
||||
struct item_data *i_data;
|
||||
|
||||
@ -2975,6 +2983,11 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
|
||||
continue;
|
||||
|
||||
temp = mdrop[i].rate;
|
||||
|
||||
#if defined(RENEWAL_DROP)
|
||||
temp = cap_value( apply_rate( temp, penalty ), 0, 10000 );
|
||||
#endif
|
||||
|
||||
if (temp != 10000) {
|
||||
if(temp <= 0 && !battle_config.drop_rate0item)
|
||||
temp = 1;
|
||||
|
@ -1115,7 +1115,7 @@ void party_exp_share(struct party_data* p, struct block_list* src, unsigned int
|
||||
#ifdef RENEWAL_EXP
|
||||
uint32 base_gained = base_exp, job_gained = job_exp;
|
||||
if (base_exp || job_exp) {
|
||||
int rate = pc_level_penalty_mod(md->level - sd[i]->status.base_level, md->db->status.class_, md->db->status.mode, 1);
|
||||
int rate = pc_level_penalty_mod( sd[i], PENALTY_EXP, nullptr, md );
|
||||
if (rate != 100) {
|
||||
if (base_exp)
|
||||
base_gained = (unsigned int)cap_value(apply_rate(base_exp, rate), 1, UINT_MAX);
|
||||
|
185
src/map/pc.cpp
185
src/map/pc.cpp
@ -67,9 +67,6 @@ static inline bool pc_attendance_rewarded_today( struct map_session_data* sd );
|
||||
#define PVP_CALCRANK_INTERVAL 1000 // PVP calculation interval
|
||||
|
||||
static unsigned int statp[MAX_LEVEL+1];
|
||||
#if defined(RENEWAL_DROP) || defined(RENEWAL_EXP)
|
||||
static unsigned int level_penalty[3][CLASS_MAX][MAX_LEVEL*2+1];
|
||||
#endif
|
||||
|
||||
// h-files are for declarations, not for implementations... [Shinomori]
|
||||
struct skill_tree_entry skill_tree[CLASS_COUNT][MAX_SKILL_TREE];
|
||||
@ -267,6 +264,105 @@ uint64 AttendanceDatabase::parseBodyNode(const YAML::Node &node){
|
||||
|
||||
AttendanceDatabase attendance_db;
|
||||
|
||||
const std::string PenaltyDatabase::getDefaultLocation(){
|
||||
return std::string( db_path ) + "/level_penalty.yml";
|
||||
}
|
||||
|
||||
uint64 PenaltyDatabase::parseBodyNode( const YAML::Node& node ){
|
||||
std::string type_constant;
|
||||
|
||||
if( !this->asString( node, "Type", type_constant ) ){
|
||||
return 0;
|
||||
}
|
||||
|
||||
int64 constant_value;
|
||||
|
||||
if( !script_get_constant( ( "PENALTY_" + type_constant ).c_str(), &constant_value ) ){
|
||||
this->invalidWarning( node["Type"], "Unknown penalty type \"%s\".\n", type_constant.c_str() );
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( constant_value < PENALTY_NONE || constant_value > PENALTY_MAX ){
|
||||
this->invalidWarning( node["Type"], "Invalid penalty type \"%s\".\n", type_constant.c_str() );
|
||||
return 0;
|
||||
}
|
||||
|
||||
e_penalty_type type = static_cast<e_penalty_type>( constant_value );
|
||||
|
||||
std::shared_ptr<s_penalty> penalty = this->find( type );
|
||||
bool exists = penalty != nullptr;
|
||||
|
||||
if( !exists ){
|
||||
penalty = std::make_shared<s_penalty>();
|
||||
penalty->type = type;
|
||||
|
||||
for( int i = 0, max = ARRAYLENGTH( penalty->rate ); i < max; i++ ){
|
||||
penalty->rate[i] = UINT16_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
if( this->nodeExists( node, "LevelDifferences" ) ){
|
||||
for( const YAML::Node& levelNode : node["LevelDifferences"] ){
|
||||
if( !this->nodesExist( levelNode, { "Difference", "Rate" } ) ){
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32 difference;
|
||||
|
||||
if( !this->asInt32( levelNode, "Difference", difference ) ){
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( std::abs( difference ) > MAX_LEVEL ){
|
||||
this->invalidWarning( levelNode["Difference"], "Level difference %d is bigger than maximum level %d.\n", difference, MAX_LEVEL );
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16 rate;
|
||||
|
||||
if( !this->asUInt16Rate( levelNode, "Rate", rate ) ){
|
||||
return 0;
|
||||
}
|
||||
|
||||
penalty->rate[difference + MAX_LEVEL - 1] = rate;
|
||||
}
|
||||
}
|
||||
|
||||
if( !exists ){
|
||||
this->put( type, penalty );
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void PenaltyDatabase::loadingFinished(){
|
||||
for( const auto& pair : *this ){
|
||||
for( int i = MAX_LEVEL - 1, max = ARRAYLENGTH( pair.second->rate ), last_rate = 100; i < max; i++ ){
|
||||
uint16 rate = pair.second->rate[i];
|
||||
|
||||
// Check if it has been defined
|
||||
if( rate == UINT16_MAX ){
|
||||
pair.second->rate[i] = last_rate;
|
||||
}else{
|
||||
last_rate = rate;
|
||||
}
|
||||
}
|
||||
|
||||
for( int i = MAX_LEVEL - 1, last_rate = 100; i >= 0; i-- ){
|
||||
uint16 rate = pair.second->rate[i];
|
||||
|
||||
// Check if it has been defined
|
||||
if( rate == UINT16_MAX ){
|
||||
pair.second->rate[i] = last_rate;
|
||||
}else{
|
||||
last_rate = rate;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PenaltyDatabase penalty_db;
|
||||
|
||||
#define MOTD_LINE_SIZE 128
|
||||
static char motd_text[MOTD_LINE_SIZE][CHAT_SIZE_MAX]; // Message of the day buffer [Valaris]
|
||||
|
||||
@ -11727,20 +11823,36 @@ void pc_delspiritcharm(struct map_session_data *sd, int count, int type)
|
||||
* @param type: 1 - EXP, 2 - Item Drop
|
||||
* @return Penalty rate
|
||||
*/
|
||||
int pc_level_penalty_mod(int level_diff, uint32 mob_class, enum e_mode mode, int type)
|
||||
{
|
||||
int rate = 100;
|
||||
uint16 pc_level_penalty_mod( struct map_session_data* sd, e_penalty_type type, struct mob_db* mob, mob_data* md ){
|
||||
// No player was attached, we don't use any modifier (100 = rates are not touched)
|
||||
if( sd == nullptr ){
|
||||
return 100;
|
||||
}
|
||||
|
||||
if (type == 2 && (mode&MD_FIXED_ITEMDROP))
|
||||
return rate;
|
||||
int monster_level;
|
||||
|
||||
if (level_diff < 0)
|
||||
level_diff = MAX_LEVEL + (~level_diff + 1);
|
||||
if( md != nullptr ){
|
||||
monster_level = md->level;
|
||||
mob = md->db;
|
||||
}else if( mob != nullptr ){
|
||||
monster_level = mob->lv;
|
||||
}else{
|
||||
return 100;
|
||||
}
|
||||
|
||||
if ((rate = level_penalty[type][mob_class][level_diff]) > 0) // Monster class found, return rate
|
||||
return rate;
|
||||
if( ( type == PENALTY_DROP || type == PENALTY_MVP_DROP ) && status_has_mode( &mob->status, MD_FIXED_ITEMDROP ) ){
|
||||
return 100;
|
||||
}
|
||||
|
||||
return 100; // Penalty not found, return default
|
||||
int level_difference = monster_level - sd->status.base_level;
|
||||
|
||||
std::shared_ptr<s_penalty> penalty = penalty_db.find( type );
|
||||
|
||||
if( penalty != nullptr ){
|
||||
return penalty->rate[ level_difference + MAX_LEVEL - 1 ];
|
||||
}else{
|
||||
return 100;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -11897,35 +12009,6 @@ static bool pc_readdb_skilltree(char* fields[], int columns, int current)
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#if defined(RENEWAL_DROP) || defined(RENEWAL_EXP)
|
||||
static bool pc_readdb_levelpenalty(char* fields[], int columns, int current)
|
||||
{
|
||||
int type, class_, diff;
|
||||
|
||||
type = atoi(fields[0]); //1=experience, 2=item drop
|
||||
class_ = atoi(fields[1]);
|
||||
diff = atoi(fields[2]);
|
||||
|
||||
if( type != 1 && type != 2 ){
|
||||
ShowWarning("pc_readdb_levelpenalty: Invalid type %d specified.\n", type);
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !CHK_CLASS(class_) ){
|
||||
ShowWarning("pc_readdb_levelpenalty: Invalid class %d specified.\n", class_);
|
||||
return false;
|
||||
}
|
||||
|
||||
diff = min(diff, MAX_LEVEL);
|
||||
|
||||
if( diff < 0 )
|
||||
diff = min(MAX_LEVEL + ( ~(diff) + 1 ), MAX_LEVEL*2);
|
||||
|
||||
level_penalty[type][class_][diff] = atoi(fields[3]);
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
/** [Cydh]
|
||||
* Calculates base hp of player. Reference: http://irowiki.org/wiki/Max_HP
|
||||
@ -12303,22 +12386,7 @@ void pc_readdb(void) {
|
||||
memset(job_info,0,sizeof(job_info)); // job_info table
|
||||
|
||||
#if defined(RENEWAL_DROP) || defined(RENEWAL_EXP)
|
||||
sv_readdb(db_path, DBPATH "level_penalty.txt", ',', 4, 4, -1, &pc_readdb_levelpenalty, 0);
|
||||
sv_readdb(db_path, DBIMPORT"/level_penalty.txt", ',', 4, 4, -1, &pc_readdb_levelpenalty, 1);
|
||||
for( k=1; k < 3; k++ ){ // fill in the blanks
|
||||
int j;
|
||||
for( j = 0; j < CLASS_ALL; j++ ){
|
||||
int tmp = 0;
|
||||
for( i = 0; i < MAX_LEVEL*2; i++ ){
|
||||
if( i == MAX_LEVEL+1 )
|
||||
tmp = level_penalty[k][j][0];// reset
|
||||
if( level_penalty[k][j][i] > 0 )
|
||||
tmp = level_penalty[k][j][i];
|
||||
else
|
||||
level_penalty[k][j][i] = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
penalty_db.load();
|
||||
#endif
|
||||
|
||||
// reset then read statspoint
|
||||
@ -13576,6 +13644,7 @@ void do_final_pc(void) {
|
||||
ers_destroy(str_reg_ers);
|
||||
|
||||
attendance_db.clear();
|
||||
penalty_db.clear();
|
||||
}
|
||||
|
||||
void do_init_pc(void) {
|
||||
|
@ -7,6 +7,8 @@
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "../common/cbasetypes.hpp"
|
||||
#include "../common/database.hpp"
|
||||
#include "../common/mmo.hpp" // JOB_*, MAX_FAME_LIST, struct fame_list, struct mmo_charstatus
|
||||
#include "../common/strlib.hpp"// StringBuf
|
||||
#include "../common/timer.hpp"
|
||||
@ -895,6 +897,31 @@ enum item_check {
|
||||
ITMCHK_ALL = ITMCHK_INVENTORY|ITMCHK_CART|ITMCHK_STORAGE,
|
||||
};
|
||||
|
||||
enum e_penalty_type : uint16{
|
||||
PENALTY_NONE,
|
||||
PENALTY_EXP,
|
||||
PENALTY_DROP,
|
||||
PENALTY_MVP_EXP,
|
||||
PENALTY_MVP_DROP,
|
||||
PENALTY_MAX
|
||||
};
|
||||
|
||||
struct s_penalty{
|
||||
e_penalty_type type;
|
||||
uint16 rate[MAX_LEVEL * 2 - 1];
|
||||
};
|
||||
|
||||
class PenaltyDatabase : public TypesafeYamlDatabase<uint16, s_penalty> {
|
||||
public:
|
||||
PenaltyDatabase() : TypesafeYamlDatabase( "PENALTY_DB", 1 ){
|
||||
|
||||
}
|
||||
|
||||
const std::string getDefaultLocation();
|
||||
uint64 parseBodyNode(const YAML::Node& node);
|
||||
void loadingFinished();
|
||||
};
|
||||
|
||||
struct s_job_info {
|
||||
unsigned int base_hp[MAX_LEVEL], base_sp[MAX_LEVEL]; //Storage for the first calculation with hp/sp factor and multiplicator
|
||||
int hp_factor, hp_multiplicator, sp_factor;
|
||||
@ -1420,7 +1447,7 @@ void pc_show_questinfo_reinit(struct map_session_data *sd);
|
||||
bool pc_job_can_entermap(enum e_job jobid, int m, int group_lv);
|
||||
|
||||
#if defined(RENEWAL_DROP) || defined(RENEWAL_EXP)
|
||||
int pc_level_penalty_mod(int level_diff, uint32 mob_class, enum e_mode mode, int type);
|
||||
uint16 pc_level_penalty_mod( struct map_session_data* sd, e_penalty_type type, struct mob_db* mob, mob_data* md = nullptr );
|
||||
#endif
|
||||
|
||||
bool pc_attendance_enabled();
|
||||
|
@ -7981,6 +7981,12 @@
|
||||
export_constant(DROPEFFECT_ORANGE_PILLAR);
|
||||
export_constant(DROPEFFECT_MAX);
|
||||
|
||||
/* penalty types */
|
||||
export_constant(PENALTY_EXP);
|
||||
export_constant(PENALTY_DROP);
|
||||
export_constant(PENALTY_MVP_EXP);
|
||||
export_constant(PENALTY_MVP_DROP);
|
||||
|
||||
#undef export_constant
|
||||
#undef export_constant2
|
||||
#undef export_parameter
|
||||
|
@ -87,6 +87,8 @@ std::unordered_map<uint16, s_skill_unit_csv> skill_unit;
|
||||
std::unordered_map<uint16, s_skill_copyable> skill_copyable;
|
||||
std::unordered_map<uint16, s_skill_db> skill_nearnpc;
|
||||
|
||||
static unsigned int level_penalty[3][CLASS_MAX][MAX_LEVEL * 2 + 1];
|
||||
|
||||
struct s_item_flag_csv2yaml {
|
||||
bool buyingstore, dead_branch, group, guid, broadcast, bindOnEquip, delay_consume;
|
||||
e_item_drop_effect dropEffect;
|
||||
@ -215,6 +217,8 @@ static bool itemdb_read_db(const char *file);
|
||||
static bool itemdb_read_randomopt(const char* file);
|
||||
static bool itemdb_read_randomopt_group(char *str[], int columns, int current);
|
||||
static bool itemdb_randomopt_group_yaml(void);
|
||||
static bool pc_readdb_levelpenalty(char* fields[], int columns, int current);
|
||||
static bool pc_levelpenalty_yaml();
|
||||
|
||||
// Constants for conversion
|
||||
std::unordered_map<t_itemid, std::string> aegis_itemnames;
|
||||
@ -537,6 +541,22 @@ int do_init( int argc, char** argv ){
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef RENEWAL
|
||||
memset( level_penalty, 0, sizeof( level_penalty ) );
|
||||
if (!process("PENALTY_DB", 1, { path_db_mode }, "level_penalty", [](const std::string& path, const std::string& name_ext) -> bool {
|
||||
return sv_readdb(path.c_str(), name_ext.c_str(), ',', 4, 4, -1, &pc_readdb_levelpenalty, false) && pc_levelpenalty_yaml();
|
||||
})) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
memset( level_penalty, 0, sizeof( level_penalty ) );
|
||||
if (!process("PENALTY_DB", 1, { path_db_import }, "level_penalty", [](const std::string& path, const std::string& name_ext) -> bool {
|
||||
return sv_readdb(path.c_str(), name_ext.c_str(), ',', 4, 4, -1, &pc_readdb_levelpenalty, false) && pc_levelpenalty_yaml();
|
||||
})) {
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
// TODO: add implementations ;-)
|
||||
|
||||
return 0;
|
||||
@ -3538,6 +3558,67 @@ static bool itemdb_randomopt_group_yaml(void) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool pc_readdb_levelpenalty( char* fields[], int columns, int current ){
|
||||
// 1=experience, 2=item drop
|
||||
int type = atoi( fields[0] );
|
||||
|
||||
if( type != 1 && type != 2 ){
|
||||
ShowWarning( "pc_readdb_levelpenalty: Invalid type %d specified.\n", type );
|
||||
return false;
|
||||
}
|
||||
|
||||
int64 val = constant_lookup_int( fields[1] );
|
||||
|
||||
if( val == -100 ){
|
||||
ShowWarning("pc_readdb_levelpenalty: Unknown class constant %s specified.\n", fields[1] );
|
||||
return false;
|
||||
}
|
||||
|
||||
int class_ = atoi( fields[1] );
|
||||
|
||||
if( !CHK_CLASS( class_ ) ){
|
||||
ShowWarning( "pc_readdb_levelpenalty: Invalid class %d specified.\n", class_ );
|
||||
return false;
|
||||
}
|
||||
|
||||
int diff = atoi( fields[2] );
|
||||
|
||||
if( std::abs( diff ) > MAX_LEVEL ){
|
||||
ShowWarning( "pc_readdb_levelpenalty: Level difference %d is too high.\n", diff );
|
||||
return false;
|
||||
}
|
||||
|
||||
diff += MAX_LEVEL - 1;
|
||||
|
||||
level_penalty[type][class_][diff] = atoi(fields[3]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void pc_levelpenalty_yaml_sub( int type, const std::string& name ){
|
||||
body << YAML::BeginMap;
|
||||
body << YAML::Key << "Type" << YAML::Value << name;
|
||||
body << YAML::Key << "LevelDifferences";
|
||||
body << YAML::BeginSeq;
|
||||
for( int i = ARRAYLENGTH( level_penalty[type][CLASS_NORMAL] ); i >= 0; i-- ){
|
||||
if( level_penalty[type][CLASS_NORMAL][i] > 0 && level_penalty[type][CLASS_NORMAL][i] != 100 ){
|
||||
body << YAML::BeginMap;
|
||||
body << YAML::Key << "Difference" << YAML::Value << ( i - MAX_LEVEL + 1 );
|
||||
body << YAML::Key << "Rate" << YAML::Value << level_penalty[type][CLASS_NORMAL][i];
|
||||
body << YAML::EndMap;
|
||||
}
|
||||
}
|
||||
body << YAML::EndSeq;
|
||||
body << YAML::EndMap;
|
||||
}
|
||||
|
||||
bool pc_levelpenalty_yaml(){
|
||||
pc_levelpenalty_yaml_sub( 1, "Exp" );
|
||||
pc_levelpenalty_yaml_sub( 2, "Drop" );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Initialize Random Option constants
|
||||
void init_random_option_constants() {
|
||||
#define export_constant2(a, b) script_set_constant_(a, b, a, false, false)
|
||||
|
Loading…
x
Reference in New Issue
Block a user