Fixes HP/SP table issues (#6361)
* Fixes #6360. * Adds missing HP/SP values for Rebellion, Baby Rebellion, Expanded Super Novice, Expanded Super Baby, Baby Summoner, Star Emperor, Baby Star Emperor, Soul Reaper, and Baby Soul Reaper. * Adds official HP/SP values for Summoner, Baby Summoner, Star Emperor, Baby Star Emperor, Soul Reaper, and Baby Soul Reaper. These are missing levels 176-200 though. * Fixes the BonusStats parser to properly check for the max job level. * Adds several logical checks for blocking level 0 during parse. * Adds several logical checks for skipping content over a job's max level for HP/SP and BEXP/JEXP. * Fixes the SP values being filled against the max job level instead of base level if the HP/SP Table wasn't being used. * The parser will now properly fill the HP/SP array with 0's so that the loadingFinished() function can properly calculate a value to insert if something is missing. * Adds a better solution to CSV2YAML when checking for the max base level when converting HP/SP. * Fixes the CSV2YAML generating bad job bonus stat conversions. Thanks to @kaninhot004 and @Lemongrass3110! Co-authored-by: Lemongrass3110 <lemongrass@kstp.at>
This commit is contained in:
parent
9d6a78cf68
commit
fe0d445500
File diff suppressed because it is too large
Load Diff
@ -8535,24 +8535,6 @@ Body:
|
||||
Str: 1
|
||||
- Level: 50
|
||||
Dex: 1
|
||||
- Level: 59
|
||||
Str: 1
|
||||
- Level: 63
|
||||
Str: 1
|
||||
- Level: 64
|
||||
Str: 1
|
||||
- Level: 65
|
||||
Str: 1
|
||||
- Level: 66
|
||||
Str: 1
|
||||
- Level: 67
|
||||
Str: 1
|
||||
- Level: 68
|
||||
Str: 1
|
||||
- Level: 69
|
||||
Str: 1
|
||||
- Level: 70
|
||||
Str: 1
|
||||
- Jobs:
|
||||
Oboro: true
|
||||
MaxWeight: 26000
|
||||
@ -8634,20 +8616,6 @@ Body:
|
||||
Str: 1
|
||||
- Level: 50
|
||||
Dex: 1
|
||||
- Level: 59
|
||||
Str: 1
|
||||
- Level: 63
|
||||
Agi: 1
|
||||
- Level: 64
|
||||
Agi: 1
|
||||
- Level: 65
|
||||
Agi: 1
|
||||
- Level: 66
|
||||
Int: 1
|
||||
- Level: 68
|
||||
Vit: 1
|
||||
- Level: 70
|
||||
Vit: 1
|
||||
- Jobs:
|
||||
Rebellion: true
|
||||
MaxWeight: 28000
|
||||
@ -8812,8 +8780,6 @@ Body:
|
||||
Agi: 1
|
||||
- Level: 50
|
||||
Dex: 1
|
||||
- Level: 59
|
||||
Str: 1
|
||||
- Jobs:
|
||||
Baby_Summoner: true
|
||||
HpFactor: 100
|
||||
@ -8892,8 +8858,6 @@ Body:
|
||||
Agi: 1
|
||||
- Level: 50
|
||||
Dex: 1
|
||||
- Level: 59
|
||||
Str: 1
|
||||
- Jobs:
|
||||
Baby_Ninja: true
|
||||
MaxWeight: 26000
|
||||
@ -9036,18 +9000,6 @@ Body:
|
||||
Str: 1
|
||||
- Level: 50
|
||||
Dex: 1
|
||||
- Level: 59
|
||||
Str: 1
|
||||
- Level: 63
|
||||
Str: 1
|
||||
- Level: 64
|
||||
Str: 1
|
||||
- Level: 65
|
||||
Str: 1
|
||||
- Level: 69
|
||||
Agi: 1
|
||||
- Level: 70
|
||||
Agi: 1
|
||||
- Jobs:
|
||||
Baby_Oboro: true
|
||||
MaxWeight: 26000
|
||||
@ -9129,20 +9081,6 @@ Body:
|
||||
Str: 1
|
||||
- Level: 50
|
||||
Dex: 1
|
||||
- Level: 59
|
||||
Str: 1
|
||||
- Level: 63
|
||||
Str: 1
|
||||
- Level: 64
|
||||
Str: 1
|
||||
- Level: 65
|
||||
Str: 1
|
||||
- Level: 66
|
||||
Str: 1
|
||||
- Level: 67
|
||||
Str: 1
|
||||
- Level: 68
|
||||
Str: 1
|
||||
- Jobs:
|
||||
Baby_Taekwon: true
|
||||
MaxWeight: 28000
|
||||
@ -9915,108 +9853,3 @@ Body:
|
||||
Int: 1
|
||||
- Level: 59
|
||||
Int: 1
|
||||
MaxWeight: 28000
|
||||
HpFactor: 90
|
||||
HpMultiplicator: 650
|
||||
SpFactor: 470
|
||||
BaseASPD:
|
||||
Fist: 40
|
||||
Dagger: 50
|
||||
1hSword: 50
|
||||
2hSword: 50
|
||||
1hSpear: 50
|
||||
2hSpear: 50
|
||||
1hAxe: 50
|
||||
2hAxe: 50
|
||||
Mace: 50
|
||||
2hMace: 50
|
||||
Staff: 50
|
||||
Bow: 50
|
||||
Knuckle: 50
|
||||
Musical: 50
|
||||
Whip: 50
|
||||
Book: 50
|
||||
Katar: 50
|
||||
Revolver: 50
|
||||
Rifle: 50
|
||||
Gatling: 50
|
||||
Shotgun: 50
|
||||
Grenade: 50
|
||||
Huuma: 50
|
||||
2hStaff: 50
|
||||
Shield: 6
|
||||
BonusStats:
|
||||
- Level: 1
|
||||
Str: 1
|
||||
- Level: 2
|
||||
Dex: 1
|
||||
- Level: 5
|
||||
Agi: 1
|
||||
- Level: 7
|
||||
Int: 1
|
||||
- Level: 8
|
||||
Str: 1
|
||||
- Level: 9
|
||||
Luk: 1
|
||||
- Level: 11
|
||||
Dex: 1
|
||||
- Level: 12
|
||||
Str: 1
|
||||
- Level: 13
|
||||
Agi: 1
|
||||
- Level: 15
|
||||
Int: 1
|
||||
- Level: 16
|
||||
Luk: 1
|
||||
- Level: 17
|
||||
Vit: 1
|
||||
- Level: 19
|
||||
Str: 1
|
||||
- Level: 20
|
||||
Dex: 1
|
||||
- Level: 21
|
||||
Agi: 1
|
||||
- Level: 23
|
||||
Str: 1
|
||||
- Level: 24
|
||||
Vit: 1
|
||||
- Level: 25
|
||||
Int: 1
|
||||
- Level: 27
|
||||
Dex: 1
|
||||
- Level: 29
|
||||
Agi: 1
|
||||
- Level: 30
|
||||
Dex: 1
|
||||
- Level: 31
|
||||
Str: 1
|
||||
- Level: 34
|
||||
Dex: 1
|
||||
- Level: 35
|
||||
Agi: 1
|
||||
- Level: 36
|
||||
Luk: 1
|
||||
- Level: 37
|
||||
Vit: 1
|
||||
- Level: 38
|
||||
Dex: 1
|
||||
- Level: 39
|
||||
Str: 1
|
||||
- Level: 41
|
||||
Agi: 1
|
||||
- Level: 42
|
||||
Vit: 1
|
||||
- Level: 43
|
||||
Str: 1
|
||||
- Level: 45
|
||||
Dex: 1
|
||||
- Level: 47
|
||||
Agi: 1
|
||||
- Level: 48
|
||||
Str: 1
|
||||
- Level: 50
|
||||
Dex: 1
|
||||
- Level: 56
|
||||
Str: 1
|
||||
- Level: 59
|
||||
Agi: 1
|
||||
|
127
src/map/pc.cpp
127
src/map/pc.cpp
@ -12249,9 +12249,22 @@ uint64 JobDatabase::parseBodyNode(const YAML::Node &node) {
|
||||
std::shared_ptr<s_job_info> job = job_db.find(static_cast<uint16>(job_id));
|
||||
bool exists = job != nullptr;
|
||||
|
||||
if (!exists)
|
||||
if (!exists) {
|
||||
job = std::make_shared<s_job_info>();
|
||||
|
||||
job->job_bonus.resize(MAX_LEVEL);
|
||||
std::fill(job->job_bonus.begin(), job->job_bonus.end(), std::array<uint16, PARAM_MAX> { 0 });
|
||||
|
||||
job->base_hp.resize(MAX_LEVEL);
|
||||
std::fill(job->base_hp.begin(), job->base_hp.end(), 0);
|
||||
|
||||
job->base_sp.resize(MAX_LEVEL);
|
||||
std::fill(job->base_sp.begin(), job->base_sp.end(), 0);
|
||||
|
||||
job->base_ap.resize(MAX_LEVEL);
|
||||
std::fill(job->base_ap.begin(), job->base_ap.end(), 0);
|
||||
}
|
||||
|
||||
if (this->nodeExists(node, "MaxWeight")) {
|
||||
uint32 weight;
|
||||
|
||||
@ -12336,34 +12349,6 @@ uint64 JobDatabase::parseBodyNode(const YAML::Node &node) {
|
||||
}
|
||||
}
|
||||
|
||||
if (this->nodeExists(node, "BonusStats")) {
|
||||
const YAML::Node &bonusNode = node["BonusStats"];
|
||||
job->job_bonus.resize(MAX_LEVEL);
|
||||
|
||||
for (const YAML::Node &levelNode : bonusNode) {
|
||||
uint16 level;
|
||||
|
||||
if (!this->asUInt16(levelNode, "Level", level))
|
||||
return 0;
|
||||
|
||||
if (level > MAX_LEVEL) {
|
||||
this->invalidWarning(levelNode["Level"], "Level must be between 1~MAX_LEVEL for %s.\n", job_name.c_str());
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (uint8 idx = PARAM_STR; idx < PARAM_MAX; idx++) {
|
||||
if (this->nodeExists(levelNode, parameter_names[idx])) {
|
||||
int16 change;
|
||||
|
||||
if (!this->asInt16(levelNode, parameter_names[idx], change))
|
||||
return 0;
|
||||
|
||||
job->job_bonus[level - 1][idx] = change;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this->nodeExists(node, "MaxStats")) {
|
||||
const YAML::Node &statNode = node["MaxStats"];
|
||||
|
||||
@ -12396,7 +12381,7 @@ uint64 JobDatabase::parseBodyNode(const YAML::Node &node) {
|
||||
if (!this->asUInt16(node, "MaxBaseLevel", level))
|
||||
return 0;
|
||||
|
||||
if (level > MAX_LEVEL) {
|
||||
if (level == 0 || level > MAX_LEVEL) {
|
||||
this->invalidWarning(node["MaxBaseLevel"], "MaxBaseLevel must be between 1~MAX_LEVEL for %s, capping to MAX_LEVEL.\n", job_name.c_str());
|
||||
level = MAX_LEVEL;
|
||||
}
|
||||
@ -12414,7 +12399,10 @@ uint64 JobDatabase::parseBodyNode(const YAML::Node &node) {
|
||||
if (!this->asUInt16(bexpNode, "Level", level))
|
||||
return 0;
|
||||
|
||||
if (level < 1 || level > MAX_LEVEL) {
|
||||
if (level > job->max_base_level)
|
||||
continue;
|
||||
|
||||
if (level == 0 || level > MAX_LEVEL) {
|
||||
this->invalidWarning(bexpNode["Level"], "Level must be between 1~MAX_LEVEL for %s.\n", job_name.c_str());
|
||||
return 0;
|
||||
}
|
||||
@ -12436,13 +12424,12 @@ uint64 JobDatabase::parseBodyNode(const YAML::Node &node) {
|
||||
if (!this->asUInt16(node, "MaxJobLevel", level))
|
||||
return 0;
|
||||
|
||||
if (level > MAX_LEVEL) {
|
||||
if (level == 0 || level > MAX_LEVEL) {
|
||||
this->invalidWarning(node["MaxJobLevel"], "MaxJobLevel must be between 1~MAX_LEVEL for %s, capping to MAX_LEVEL.\n", job_name.c_str());
|
||||
level = MAX_LEVEL;
|
||||
}
|
||||
|
||||
job->max_job_level = level;
|
||||
job->job_bonus.resize(level);
|
||||
} else {
|
||||
if (!exists)
|
||||
job->max_job_level = MAX_LEVEL;
|
||||
@ -12455,7 +12442,10 @@ uint64 JobDatabase::parseBodyNode(const YAML::Node &node) {
|
||||
if (!this->asUInt16(jexpNode, "Level", level))
|
||||
return 0;
|
||||
|
||||
if (level < 1 || level > MAX_LEVEL) {
|
||||
if (level > job->max_job_level)
|
||||
continue;
|
||||
|
||||
if (level == 0 || level > MAX_LEVEL) {
|
||||
this->invalidWarning(jexpNode["Level"], "Level must be between 1~MAX_LEVEL for %s.\n", job_name.c_str());
|
||||
return 0;
|
||||
}
|
||||
@ -12471,17 +12461,45 @@ uint64 JobDatabase::parseBodyNode(const YAML::Node &node) {
|
||||
}
|
||||
}
|
||||
|
||||
if (this->nodeExists(node, "BonusStats")) {
|
||||
const YAML::Node &bonusNode = node["BonusStats"];
|
||||
|
||||
for (const YAML::Node &levelNode : bonusNode) {
|
||||
uint16 level;
|
||||
|
||||
if (!this->asUInt16(levelNode, "Level", level))
|
||||
return 0;
|
||||
|
||||
if (level == 0 || level > MAX_LEVEL) {
|
||||
this->invalidWarning(levelNode["Level"], "Level must be between 1~MAX_LEVEL for %s.\n", job_name.c_str());
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (uint8 idx = PARAM_STR; idx < PARAM_MAX; idx++) {
|
||||
if (this->nodeExists(levelNode, parameter_names[idx])) {
|
||||
int16 change;
|
||||
|
||||
if (!this->asInt16(levelNode, parameter_names[idx], change))
|
||||
return 0;
|
||||
|
||||
job->job_bonus[level - 1][idx] = change;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HP_SP_TABLES
|
||||
if (this->nodeExists(node, "BaseHp")) {
|
||||
job->base_hp.resize(job->max_base_level, 1);
|
||||
|
||||
for (const YAML::Node &bhpNode : node["BaseHp"]) {
|
||||
uint16 level;
|
||||
|
||||
if (!this->asUInt16(bhpNode, "Level", level))
|
||||
return 0;
|
||||
|
||||
if (level > MAX_LEVEL) {
|
||||
if (level > job->max_base_level)
|
||||
continue;
|
||||
|
||||
if (level == 0 || level > MAX_LEVEL) {
|
||||
this->invalidWarning(bhpNode["Level"], "Level must be between 1~MAX_LEVEL for %s.\n", job_name.c_str());
|
||||
return 0;
|
||||
}
|
||||
@ -12498,15 +12516,16 @@ uint64 JobDatabase::parseBodyNode(const YAML::Node &node) {
|
||||
}
|
||||
|
||||
if (this->nodeExists(node, "BaseSp")) {
|
||||
job->base_sp.resize(job->max_base_level, 1);
|
||||
|
||||
for (const YAML::Node &bspNode : node["BaseSp"]) {
|
||||
uint16 level;
|
||||
|
||||
if (!this->asUInt16(bspNode, "Level", level))
|
||||
return 0;
|
||||
|
||||
if (level > MAX_LEVEL) {
|
||||
if (level > job->max_base_level)
|
||||
continue;
|
||||
|
||||
if (level == 0 || level > MAX_LEVEL) {
|
||||
this->invalidWarning(bspNode["Level"], "Level must be between 1~MAX_LEVEL for %s.\n", job_name.c_str());
|
||||
return 0;
|
||||
}
|
||||
@ -12523,15 +12542,16 @@ uint64 JobDatabase::parseBodyNode(const YAML::Node &node) {
|
||||
}
|
||||
|
||||
if (this->nodeExists(node, "BaseAp")) {
|
||||
job->base_ap.resize(job->max_base_level, 1);
|
||||
|
||||
for (const YAML::Node &bapNode : node["BaseAp"]) {
|
||||
uint16 level;
|
||||
|
||||
if (!this->asUInt16(bapNode, "Level", level))
|
||||
return 0;
|
||||
|
||||
if (level > MAX_LEVEL) {
|
||||
if (level > job->max_base_level)
|
||||
continue;
|
||||
|
||||
if (level == 0 || level > MAX_LEVEL) {
|
||||
this->invalidWarning(bapNode["Level"], "Level must be between 1~MAX_LEVEL for %s.\n", job_name.c_str());
|
||||
return 0;
|
||||
}
|
||||
@ -12575,21 +12595,30 @@ void JobDatabase::loadingFinished() {
|
||||
ShowWarning("Class %s (%d) does not have a job exp table.\n", job_name(job_id), job_id);
|
||||
|
||||
// Init and checking the empty value of Base HP/SP [Cydh]
|
||||
if (job->base_hp.size() == 0)
|
||||
if (job->base_hp.empty())
|
||||
job->base_hp.resize(maxBaseLv);
|
||||
for (uint16 j = 0; j < maxBaseLv; j++) {
|
||||
if (job->base_hp[j] == 0)
|
||||
job->base_hp[j] = pc_calc_basehp(j + 1, job_id);
|
||||
}
|
||||
if (job->base_sp.size() == 0)
|
||||
job->base_sp.resize(maxJobLv);
|
||||
for (uint16 j = 0; j < maxJobLv; j++) {
|
||||
if (job->base_sp.empty())
|
||||
job->base_sp.resize(maxBaseLv);
|
||||
for (uint16 j = 0; j < maxBaseLv; j++) {
|
||||
if (job->base_sp[j] == 0)
|
||||
job->base_sp[j] = pc_calc_basesp(j + 1, job_id);
|
||||
}
|
||||
|
||||
// Resize for the maximum job level
|
||||
job->job_bonus.resize(maxJobLv);
|
||||
// Resize to the maximum base level
|
||||
if (job->base_hp.capacity() > maxBaseLv)
|
||||
job->base_hp.erase(job->base_hp.begin() + maxBaseLv, job->base_hp.end());
|
||||
if (job->base_sp.capacity() > maxBaseLv)
|
||||
job->base_sp.erase(job->base_sp.begin() + maxBaseLv, job->base_sp.end());
|
||||
if (job->base_ap.capacity() > maxBaseLv)
|
||||
job->base_ap.erase(job->base_ap.begin() + maxBaseLv, job->base_ap.end());
|
||||
|
||||
// Resize to the maximum job level
|
||||
if (job->job_bonus.capacity() > maxJobLv)
|
||||
job->job_bonus.erase(job->job_bonus.begin() + maxJobLv, job->job_bonus.end());
|
||||
|
||||
for (uint16 parameter = PARAM_STR; parameter < PARAM_MAX; parameter++) {
|
||||
// Store total
|
||||
|
@ -4162,8 +4162,11 @@ static bool read_constdb(char* fields[], int columns, int current) {
|
||||
static bool pc_readdb_job2(char* fields[], int columns, int current) {
|
||||
std::vector<int> stats;
|
||||
|
||||
stats.resize(MAX_LEVEL);
|
||||
std::fill(stats.begin(), stats.end(), 0); // Fill with 0 so we don't produce arbitrary stats
|
||||
|
||||
for (int i = 1; i < columns; i++)
|
||||
stats.insert(stats.begin() + i - 1, atoi(fields[i]));
|
||||
stats[i - 1] = atoi(fields[i]);
|
||||
|
||||
job_db2.insert({ atoi(fields[0]), stats });
|
||||
return true;
|
||||
@ -4258,17 +4261,25 @@ static bool pc_readdb_job_basehpsp(char* fields[], int columns, int current) {
|
||||
body << YAML::BeginSeq;
|
||||
|
||||
int j = 0, job_id = jobs[0], endlvl = 0;
|
||||
auto it_level = exp_base_level.find(job_id);
|
||||
|
||||
if (it_level != exp_base_level.end())
|
||||
endlvl = it_level->second;
|
||||
else {
|
||||
ShowError("pc_readdb_job_basehpsp: The job_exp database needs to be imported into memory before converting the job_basehpsp_db database.\n");
|
||||
return false;
|
||||
// Find the highest level in the group of jobs
|
||||
for (int i = 0; i < job_count; i++) {
|
||||
auto it_level = exp_base_level.find(jobs[i]);
|
||||
int tmplvl;
|
||||
|
||||
if (it_level != exp_base_level.end())
|
||||
tmplvl = it_level->second;
|
||||
else {
|
||||
ShowError("pc_readdb_job_basehpsp: The job_exp database needs to be imported into memory before converting the job_basehpsp_db database.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (endlvl < tmplvl)
|
||||
endlvl = tmplvl;
|
||||
}
|
||||
|
||||
// These jobs don't have values less than level 99
|
||||
if ((job_id >= JOB_RUNE_KNIGHT && job_id <= JOB_BABY_MECHANIC2) || job_id == JOB_KAGEROU || job_id == JOB_OBORO || job_id == JOB_REBELLION || job_id == JOB_BABY_KAGEROU || job_id == JOB_BABY_OBORO || job_id == JOB_BABY_REBELLION)
|
||||
if ((job_id >= JOB_RUNE_KNIGHT && job_id <= JOB_BABY_MECHANIC2) || job_id == JOB_KAGEROU || job_id == JOB_OBORO || job_id == JOB_REBELLION || job_id == JOB_BABY_KAGEROU || job_id == JOB_BABY_OBORO || job_id == JOB_BABY_REBELLION || job_id >= JOB_STAR_EMPEROR)
|
||||
j = 98;
|
||||
|
||||
if (type == 0) { // HP
|
||||
|
Loading…
x
Reference in New Issue
Block a user