Allow NPC view data modifications (#4385)

* Fixes #4289.
* Updated script commands setunitdata and getunitdata to support the modification of NPC view data.
* Converted mob_avail database to YAML.
Thanks to @Lemongrass3110, @4144, @exneval, @Balferian, @cahya1992 and @teededung!
Co-authored-by: Lemongrass3110 <lemongrass@kstp.at>
This commit is contained in:
Aleos
2019-12-22 10:27:43 -05:00
committed by GitHub
parent f2a1b6e784
commit b0119631a4
19 changed files with 971 additions and 160 deletions

View File

@@ -43,9 +43,9 @@
#include "../map/npc.hpp"
#include "../map/pc.hpp"
#include "../map/pet.hpp"
#include "../map/quest.hpp"
#include "../map/script.hpp"
#include "../map/storage.hpp"
#include "../map/quest.hpp"
using namespace rathena;
@@ -73,9 +73,11 @@ static bool skill_parse_row_magicmushroomdb(char* split[], int column, int curre
static bool skill_parse_row_abradb(char* split[], int columns, int current);
static bool skill_parse_row_improvisedb(char* split[], int columns, int current);
static bool skill_parse_row_spellbookdb(char* split[], int columns, int current);
static bool mob_readdb_mobavail(char *str[], int columns, int current);
// Constants for conversion
std::unordered_map<uint16, std::string> aegis_itemnames;
std::unordered_map<uint16, uint16> aegis_itemviewid;
std::unordered_map<uint16, std::string> aegis_mobnames;
std::unordered_map<uint16, std::string> aegis_skillnames;
std::unordered_map<const char*, int32> constants;
@@ -218,6 +220,7 @@ int do_init( int argc, char** argv ){
sv_readdb( path_db_import.c_str(), "skill_db.txt", ',', 18, 18, -1, parse_skill_constants, false );
// Load constants
#define export_constant_npc(a) export_constant(a)
#include "../map/script_constants.hpp"
std::vector<std::string> root_paths = {
@@ -262,6 +265,12 @@ int do_init( int argc, char** argv ){
return 0;
}
if (!process("MOB_AVAIL_DB", 1, root_paths, "mob_avail", [](const std::string& path, const std::string& name_ext) -> bool {
return sv_readdb(path.c_str(), name_ext.c_str(), ',', 2, 12, -1, &mob_readdb_mobavail, false);
})) {
return 0;
}
// TODO: add implementations ;-)
return 0;
@@ -419,6 +428,9 @@ static bool parse_item_constants( const char* path ){
aegis_itemnames[item_id] = std::string(name);
if (atoi(str[14]) & (EQP_HELM | EQP_COSTUME_HELM) && util::umap_find(aegis_itemviewid, (uint16)atoi(str[18])) == nullptr)
aegis_itemviewid[atoi(str[18])] = item_id;
count++;
}
@@ -808,3 +820,233 @@ static bool skill_parse_row_spellbookdb(char* split[], int columns, int current)
return true;
}
// Copied and adjusted from mob.cpp
static bool mob_readdb_mobavail(char* str[], int columns, int current) {
uint16 mob_id = atoi(str[0]);
std::string *mob_name = util::umap_find(aegis_mobnames, mob_id);
if (mob_name == nullptr) {
ShowWarning("mob_avail reading: Invalid mob-class %hu, Mob not read.\n", mob_id);
return false;
}
body << YAML::Key << "Mob" << YAML::Value << *mob_name;
uint16 sprite_id = atoi(str[1]);
std::string *sprite_name = util::umap_find(aegis_mobnames, sprite_id);
if (sprite_name == nullptr) {
char *sprite = const_cast<char *>(constant_lookup(sprite_id, "JOB_"));
if (sprite == nullptr) {
sprite = const_cast<char *>(constant_lookup(sprite_id, "JT_"));
if (sprite == nullptr) {
ShowError("Sprite name %s is not known.\n", sprite);
return false;
}
sprite += 3; // Strip JT_ here because the script engine doesn't send this prefix for NPC.
body << YAML::Key << "Sprite" << YAML::Value << *sprite;
} else
body << YAML::Key << "Sprite" << YAML::Value << *sprite;
} else
body << YAML::Key << "Sprite" << YAML::Value << *sprite_name;
if (columns == 12) {
body << YAML::Key << "Sex" << YAML::Value << (atoi(str[2]) ? "Male" : "Female");
if (atoi(str[3]) != 0)
body << YAML::Key << "HairStyle" << YAML::Value << atoi(str[3]);
if (atoi(str[4]) != 0)
body << YAML::Key << "HairColor" << YAML::Value << atoi(str[4]);
if (atoi(str[11]) != 0)
body << YAML::Key << "ClothColor" << YAML::Value << atoi(str[11]);
if (atoi(str[5]) != 0) {
uint16 weapon_item_id = atoi(str[5]);
std::string *weapon_item_name = util::umap_find(aegis_itemnames, weapon_item_id);
if (weapon_item_name == nullptr) {
ShowError("Item name for item ID %hu (weapon) is not known.\n", weapon_item_id);
return false;
}
body << YAML::Key << "Weapon" << YAML::Value << *weapon_item_name;
}
if (atoi(str[6]) != 0) {
uint16 shield_item_id = atoi(str[6]);
std::string *shield_item_name = util::umap_find(aegis_itemnames, shield_item_id);
if (shield_item_name == nullptr) {
ShowError("Item name for item ID %hu (shield) is not known.\n", shield_item_id);
return false;
}
body << YAML::Key << "Shield" << YAML::Value << *shield_item_name;
}
if (atoi(str[7]) != 0) {
uint16 *headtop_item_id = util::umap_find(aegis_itemviewid, (uint16)atoi(str[7]));
if (headtop_item_id == nullptr) {
ShowError("Item ID for view ID %hu (head top) is not known.\n", atoi(str[7]));
return false;
}
std::string *headtop_item_name = util::umap_find(aegis_itemnames, *headtop_item_id);
if (headtop_item_name == nullptr) {
ShowError("Item name for item ID %hu (head top) is not known.\n", *headtop_item_id);
return false;
}
body << YAML::Key << "HeadTop" << YAML::Value << *headtop_item_name;
}
if (atoi(str[8]) != 0) {
uint16 *headmid_item_id = util::umap_find(aegis_itemviewid, (uint16)atoi(str[8]));
if (headmid_item_id == nullptr) {
ShowError("Item ID for view ID %hu (head mid) is not known.\n", atoi(str[8]));
return false;
}
std::string *headmid_item_name = util::umap_find(aegis_itemnames, *headmid_item_id);
if (headmid_item_name == nullptr) {
ShowError("Item name for item ID %hu (head mid) is not known.\n", *headmid_item_id);
return false;
}
body << YAML::Key << "HeadMid" << YAML::Value << *headmid_item_name;
}
if (atoi(str[9]) != 0) {
uint16 *headlow_item_id = util::umap_find(aegis_itemviewid, (uint16)atoi(str[9]));
if (headlow_item_id == nullptr) {
ShowError("Item ID for view ID %hu (head low) is not known.\n", atoi(str[9]));
return false;
}
std::string *headlow_item_name = util::umap_find(aegis_itemnames, *headlow_item_id);
if (headlow_item_name == nullptr) {
ShowError("Item name for item ID %hu (head low) is not known.\n", *headlow_item_id);
return false;
}
body << YAML::Key << "HeadLow" << YAML::Value << *headlow_item_name;
}
if (atoi(str[10]) != 0) {
uint32 options = atoi(str[10]);
body << YAML::Key << "Options";
body << YAML::BeginMap;
while (options > OPTION_NOTHING && options <= OPTION_SUMMER2) {
if (options & OPTION_SIGHT) {
body << YAML::Key << "Sight" << YAML::Value << "true";
options &= ~OPTION_SIGHT;
} else if (options & OPTION_CART1) {
body << YAML::Key << "Cart1" << YAML::Value << "true";
options &= ~OPTION_CART1;
} else if (options & OPTION_FALCON) {
body << YAML::Key << "Falcon" << YAML::Value << "true";
options &= ~OPTION_FALCON;
} else if (options & OPTION_RIDING) {
body << YAML::Key << "Riding" << YAML::Value << "true";
options &= ~OPTION_RIDING;
} else if (options & OPTION_CART2) {
body << YAML::Key << "Cart2" << YAML::Value << "true";
options &= ~OPTION_CART2;
} else if (options & OPTION_CART3) {
body << YAML::Key << "Cart2" << YAML::Value << "true";
options &= ~OPTION_CART3;
} else if (options & OPTION_CART4) {
body << YAML::Key << "Cart4" << YAML::Value << "true";
options &= ~OPTION_CART4;
} else if (options & OPTION_CART5) {
body << YAML::Key << "Cart5" << YAML::Value << "true";
options &= ~OPTION_CART5;
} else if (options & OPTION_ORCISH) {
body << YAML::Key << "Orcish" << YAML::Value << "true";
options &= ~OPTION_ORCISH;
} else if (options & OPTION_WEDDING) {
body << YAML::Key << "Wedding" << YAML::Value << "true";
options &= ~OPTION_WEDDING;
} else if (options & OPTION_RUWACH) {
body << YAML::Key << "Ruwach" << YAML::Value << "true";
options &= ~OPTION_RUWACH;
} else if (options & OPTION_FLYING) {
body << YAML::Key << "Flying" << YAML::Value << "true";
options &= ~OPTION_FLYING;
} else if (options & OPTION_XMAS) {
body << YAML::Key << "Xmas" << YAML::Value << "true";
options &= ~OPTION_XMAS;
} else if (options & OPTION_TRANSFORM) {
body << YAML::Key << "Transform" << YAML::Value << "true";
options &= ~OPTION_TRANSFORM;
} else if (options & OPTION_SUMMER) {
body << YAML::Key << "Summer" << YAML::Value << "true";
options &= ~OPTION_SUMMER;
} else if (options & OPTION_DRAGON1) {
body << YAML::Key << "Dragon1" << YAML::Value << "true";
options &= ~OPTION_DRAGON1;
} else if (options & OPTION_WUG) {
body << YAML::Key << "Wug" << YAML::Value << "true";
options &= ~OPTION_WUG;
} else if (options & OPTION_WUGRIDER) {
body << YAML::Key << "WugRider" << YAML::Value << "true";
options &= ~OPTION_WUGRIDER;
} else if (options & OPTION_MADOGEAR) {
body << YAML::Key << "MadoGear" << YAML::Value << "true";
options &= ~OPTION_MADOGEAR;
} else if (options & OPTION_DRAGON2) {
body << YAML::Key << "Dragon2" << YAML::Value << "true";
options &= ~OPTION_DRAGON2;
} else if (options & OPTION_DRAGON3) {
body << YAML::Key << "Dragon3" << YAML::Value << "true";
options &= ~OPTION_DRAGON3;
} else if (options & OPTION_DRAGON4) {
body << YAML::Key << "Dragon4" << YAML::Value << "true";
options &= ~OPTION_DRAGON4;
} else if (options & OPTION_DRAGON5) {
body << YAML::Key << "Dragon5" << YAML::Value << "true";
options &= ~OPTION_DRAGON5;
} else if (options & OPTION_HANBOK) {
body << YAML::Key << "Hanbok" << YAML::Value << "true";
options &= ~OPTION_HANBOK;
} else if (options & OPTION_OKTOBERFEST) {
body << YAML::Key << "Oktoberfest" << YAML::Value << "true";
options &= ~OPTION_OKTOBERFEST;
} else if (options & OPTION_SUMMER2) {
body << YAML::Key << "Summer2" << YAML::Value << "true";
options &= ~OPTION_SUMMER2;
}
}
body << YAML::EndMap;
}
} else if (columns == 3) {
if (atoi(str[5]) != 0) {
uint16 peteq_item_id = atoi(str[5]);
std::string *peteq_item_name = util::umap_find(aegis_itemnames, peteq_item_id);
if (peteq_item_name == nullptr) {
ShowError("Item name for item ID %hu (pet equip) is not known.\n", peteq_item_id);
return false;
}
body << YAML::Key << "PetEquip" << YAML::Value << *peteq_item_name;
}
}
body << YAML::EndMap;
return true;
}