
* Fixes #4649. * Resolves some compile warnings for the mapcache and csv2yaml tools. Thanks to @reigneil!
2393 lines
72 KiB
C++
2393 lines
72 KiB
C++
// Copyright (c) rAthena Dev Teams - Licensed under GNU GPL
|
|
// For more information, see LICENCE in the main folder
|
|
|
|
#include <fstream>
|
|
#include <functional>
|
|
#include <iostream>
|
|
#include <locale>
|
|
#include <unordered_map>
|
|
#include <vector>
|
|
|
|
#ifdef WIN32
|
|
#include <conio.h>
|
|
#else
|
|
#include <termios.h>
|
|
#include <unistd.h>
|
|
#include <stdio.h>
|
|
#endif
|
|
|
|
#include <yaml-cpp/yaml.h>
|
|
|
|
#include "../common/cbasetypes.hpp"
|
|
#include "../common/core.hpp"
|
|
#include "../common/malloc.hpp"
|
|
#include "../common/mmo.hpp"
|
|
#include "../common/nullpo.hpp"
|
|
#include "../common/showmsg.hpp"
|
|
#include "../common/strlib.hpp"
|
|
#include "../common/utilities.hpp"
|
|
#include "../common/utils.hpp"
|
|
#ifdef WIN32
|
|
#include "../common/winapi.hpp"
|
|
#endif
|
|
|
|
// Only for constants - do not use functions of it or linking will fail
|
|
#include "../map/achievement.hpp"
|
|
#include "../map/battle.hpp"
|
|
#include "../map/battleground.hpp"
|
|
#include "../map/channel.hpp"
|
|
#include "../map/chat.hpp"
|
|
#include "../map/date.hpp"
|
|
#include "../map/instance.hpp"
|
|
#include "../map/mercenary.hpp"
|
|
#include "../map/mob.hpp"
|
|
#include "../map/npc.hpp"
|
|
#include "../map/pc.hpp"
|
|
#include "../map/pet.hpp"
|
|
#include "../map/quest.hpp"
|
|
#include "../map/script.hpp"
|
|
#include "../map/skill.hpp"
|
|
#include "../map/storage.hpp"
|
|
|
|
using namespace rathena;
|
|
|
|
#ifndef WIN32
|
|
int getch( void ){
|
|
struct termios oldattr, newattr;
|
|
int ch;
|
|
tcgetattr( STDIN_FILENO, &oldattr );
|
|
newattr = oldattr;
|
|
newattr.c_lflag &= ~( ICANON | ECHO );
|
|
tcsetattr( STDIN_FILENO, TCSANOW, &newattr );
|
|
ch = getchar();
|
|
tcsetattr( STDIN_FILENO, TCSANOW, &oldattr );
|
|
return ch;
|
|
}
|
|
#endif
|
|
|
|
// Required constant and structure definitions
|
|
#define MAX_GUILD_SKILL_REQUIRE 5
|
|
#define MAX_SKILL_ITEM_REQUIRE 10
|
|
#define MAX_SKILL_STATUS_REQUIRE 3
|
|
#define MAX_SKILL_EQUIP_REQUIRE 10
|
|
|
|
struct s_skill_unit_csv : s_skill_db {
|
|
std::string target_str;
|
|
int unit_flag_csv;
|
|
};
|
|
|
|
std::unordered_map<uint16, s_skill_require> skill_require;
|
|
std::unordered_map<uint16, s_skill_db> skill_cast;
|
|
std::unordered_map<uint16, s_skill_db> skill_castnodex;
|
|
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;
|
|
|
|
// Forward declaration of conversion functions
|
|
static bool guild_read_guildskill_tree_db( char* split[], int columns, int current );
|
|
static bool pet_read_db( const char* file );
|
|
static bool skill_parse_row_magicmushroomdb(char* split[], int column, int current);
|
|
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);
|
|
static bool skill_parse_row_requiredb(char* split[], int columns, int current);
|
|
static bool skill_parse_row_castdb(char* split[], int columns, int current);
|
|
static bool skill_parse_row_castnodexdb(char* split[], int columns, int current);
|
|
static bool skill_parse_row_unitdb(char* split[], int columns, int current);
|
|
static bool skill_parse_row_copyabledb(char* split[], int columns, int current);
|
|
static bool skill_parse_row_nonearnpcrangedb(char* split[], int columns, int current);
|
|
static bool skill_parse_row_skilldb(char* split[], 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*, int64> constants;
|
|
|
|
// Forward declaration of constant loading functions
|
|
static bool parse_item_constants( const char* path );
|
|
static bool parse_mob_constants( char* split[], int columns, int current );
|
|
static bool parse_skill_constants_txt( char* split[], int columns, int current );
|
|
static bool parse_skill_constants_yml(std::string path, std::string filename);
|
|
|
|
bool fileExists( const std::string& path );
|
|
bool askConfirmation( const char* fmt, ... );
|
|
|
|
// Skill database data to memory
|
|
static void skill_txt_data(const std::string& modePath, const std::string& fixedPath) {
|
|
skill_require.clear();
|
|
skill_cast.clear();
|
|
skill_castnodex.clear();
|
|
skill_unit.clear();
|
|
skill_copyable.clear();
|
|
skill_nearnpc.clear();
|
|
|
|
if (fileExists(modePath + "/skill_require_db.txt"))
|
|
sv_readdb(modePath.c_str(), "skill_require_db.txt", ',', 34, 34, -1, skill_parse_row_requiredb, false);
|
|
if (fileExists(modePath + "/skill_cast_db.txt"))
|
|
sv_readdb(modePath.c_str(), "skill_cast_db.txt", ',', 7, 8, -1, skill_parse_row_castdb, false);
|
|
if (fileExists(modePath + "/skill_castnodex_db.txt"))
|
|
sv_readdb(modePath.c_str(), "skill_castnodex_db.txt", ',', 2, 3, -1, skill_parse_row_castnodexdb, false);
|
|
if (fileExists(modePath + "/skill_unit_db.txt"))
|
|
sv_readdb(modePath.c_str(), "skill_unit_db.txt", ',', 8, 8, -1, skill_parse_row_unitdb, false);
|
|
if (fileExists(fixedPath + "/skill_copyable_db.txt"))
|
|
sv_readdb(fixedPath.c_str(), "skill_copyable_db.txt", ',', 2, 4, -1, skill_parse_row_copyabledb, false);
|
|
if (fileExists(fixedPath + "/skill_nonearnpc_db.txt"))
|
|
sv_readdb(fixedPath.c_str(), "skill_nonearnpc_db.txt", ',', 2, 3, -1, skill_parse_row_nonearnpcrangedb, false);
|
|
}
|
|
|
|
YAML::Emitter body;
|
|
|
|
// Implement the function instead of including the original version by linking
|
|
void script_set_constant_( const char* name, int64 value, const char* constant_name, bool isparameter, bool deprecated ){
|
|
constants[name] = value;
|
|
}
|
|
|
|
const char* constant_lookup( int32 value, const char* prefix ){
|
|
nullpo_retr( nullptr, prefix );
|
|
|
|
for( auto const& pair : constants ){
|
|
// Same prefix group and same value
|
|
if( strncasecmp( pair.first, prefix, strlen( prefix ) ) == 0 && pair.second == value ){
|
|
return pair.first;
|
|
}
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
int64 constant_lookup_int(const char* constant) {
|
|
nullpo_retr(-100, constant);
|
|
|
|
for (auto const &pair : constants) {
|
|
if (strlen(pair.first) == strlen(constant) && strncasecmp(pair.first, constant, strlen(constant)) == 0) {
|
|
return pair.second;
|
|
}
|
|
}
|
|
|
|
return -100;
|
|
}
|
|
|
|
void copyFileIfExists( std::ofstream& file,const std::string& name, bool newLine ){
|
|
std::string path = "doc/yaml/db/" + name + ".yml";
|
|
|
|
if( fileExists( path ) ){
|
|
std::ifstream source( path, std::ios::binary );
|
|
|
|
std::istreambuf_iterator<char> begin_source( source );
|
|
std::istreambuf_iterator<char> end_source;
|
|
std::ostreambuf_iterator<char> begin_dest( file );
|
|
copy( begin_source, end_source, begin_dest );
|
|
|
|
source.close();
|
|
|
|
if( newLine ){
|
|
file << "\n";
|
|
}
|
|
}
|
|
}
|
|
|
|
void prepareHeader(std::ofstream &file, const std::string& type, uint32 version, const std::string& name) {
|
|
copyFileIfExists( file, "license", false );
|
|
copyFileIfExists( file, name, true );
|
|
|
|
YAML::Emitter header(file);
|
|
|
|
header << YAML::BeginMap;
|
|
header << YAML::Key << "Header";
|
|
header << YAML::BeginMap;
|
|
header << YAML::Key << "Type" << YAML::Value << type;
|
|
header << YAML::Key << "Version" << YAML::Value << version;
|
|
header << YAML::EndMap;
|
|
header << YAML::EndMap;
|
|
|
|
file << "\n";
|
|
file << "\n";
|
|
}
|
|
|
|
void prepareBody(void) {
|
|
body << YAML::BeginMap;
|
|
body << YAML::Key << "Body";
|
|
body << YAML::BeginSeq;
|
|
}
|
|
|
|
void finalizeBody(void) {
|
|
body << YAML::EndSeq;
|
|
body << YAML::EndMap;
|
|
}
|
|
|
|
template<typename Func>
|
|
bool process( const std::string& type, uint32 version, const std::vector<std::string>& paths, const std::string& name, Func lambda, const std::string& rename = "" ){
|
|
for( const std::string& path : paths ){
|
|
const std::string name_ext = name + ".txt";
|
|
const std::string from = path + "/" + name_ext;
|
|
const std::string to = path + "/" + (rename.size() > 0 ? rename : name) + ".yml";
|
|
|
|
if( fileExists( from ) ){
|
|
if( !askConfirmation( "Found the file \"%s\", which requires migration to yml.\nDo you want to convert it now? (Y/N)\n", from.c_str() ) ){
|
|
continue;
|
|
}
|
|
|
|
if (fileExists(to)) {
|
|
if (!askConfirmation("The file \"%s\" already exists.\nDo you want to replace it? (Y/N)\n", to.c_str())) {
|
|
continue;
|
|
}
|
|
}
|
|
|
|
std::ofstream out;
|
|
|
|
body.~Emitter();
|
|
new (&body) YAML::Emitter();
|
|
out.open(to);
|
|
|
|
if (!out.is_open()) {
|
|
ShowError("Can not open file \"%s\" for writing.\n", to.c_str());
|
|
return false;
|
|
}
|
|
|
|
prepareHeader(out, type, version, (rename.size() > 0 ? rename : name));
|
|
prepareBody();
|
|
|
|
if( !lambda( path, name_ext ) ){
|
|
out.close();
|
|
return false;
|
|
}
|
|
|
|
finalizeBody();
|
|
out << body.c_str();
|
|
// Make sure there is an empty line at the end of the file for git
|
|
out << "\n";
|
|
out.close();
|
|
|
|
// TODO: do you want to delete?
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
int do_init( int argc, char** argv ){
|
|
const std::string path_db = std::string( db_path );
|
|
const std::string path_db_mode = path_db + "/" + DBPATH;
|
|
const std::string path_db_import = path_db + "/" + DBIMPORT;
|
|
|
|
// Loads required conversion constants
|
|
parse_item_constants( ( path_db_mode + "/item_db.txt" ).c_str() );
|
|
parse_item_constants( ( path_db_import + "/item_db.txt" ).c_str() );
|
|
sv_readdb( path_db_mode.c_str(), "mob_db.txt", ',', 31 + 2 * MAX_MVP_DROP + 2 * MAX_MOB_DROP, 31 + 2 * MAX_MVP_DROP + 2 * MAX_MOB_DROP, -1, &parse_mob_constants, false );
|
|
sv_readdb( path_db_import.c_str(), "mob_db.txt", ',', 31 + 2 * MAX_MVP_DROP + 2 * MAX_MOB_DROP, 31 + 2 * MAX_MVP_DROP + 2 * MAX_MOB_DROP, -1, &parse_mob_constants, false );
|
|
if (fileExists(path_db + "/" + "skill_db.yml")) {
|
|
parse_skill_constants_yml(path_db_mode, "skill_db.yml");
|
|
parse_skill_constants_yml(path_db_import + "/", "skill_db.yml");
|
|
} else {
|
|
sv_readdb(path_db_mode.c_str(), "skill_db.txt", ',', 18, 18, -1, parse_skill_constants_txt, false);
|
|
sv_readdb(path_db_import.c_str(), "skill_db.txt", ',', 18, 18, -1, parse_skill_constants_txt, false);
|
|
}
|
|
|
|
// Load constants
|
|
#define export_constant_npc(a) export_constant(a)
|
|
#include "../map/script_constants.hpp"
|
|
|
|
std::vector<std::string> root_paths = {
|
|
path_db,
|
|
path_db_mode,
|
|
path_db_import
|
|
};
|
|
|
|
if( !process( "GUILD_SKILL_TREE_DB", 1, root_paths, "guild_skill_tree", []( const std::string& path, const std::string& name_ext ) -> bool {
|
|
return sv_readdb( path.c_str(), name_ext.c_str(), ',', 2 + MAX_GUILD_SKILL_REQUIRE * 2, 2 + MAX_GUILD_SKILL_REQUIRE * 2, -1, &guild_read_guildskill_tree_db, false );
|
|
} ) ){
|
|
return 0;
|
|
}
|
|
|
|
if( !process( "PET_DB", 1, root_paths, "pet_db", []( const std::string& path, const std::string& name_ext ) -> bool {
|
|
return pet_read_db( ( path + name_ext ).c_str() );
|
|
} ) ){
|
|
return 0;
|
|
}
|
|
|
|
if (!process("MAGIC_MUSHROOM_DB", 1, root_paths, "magicmushroom_db", [](const std::string& path, const std::string& name_ext) -> bool {
|
|
return sv_readdb(path.c_str(), name_ext.c_str(), ',', 1, 1, -1, &skill_parse_row_magicmushroomdb, false);
|
|
})) {
|
|
return 0;
|
|
}
|
|
|
|
if (!process("ABRA_DB", 1, root_paths, "abra_db", [](const std::string& path, const std::string& name_ext) -> bool {
|
|
return sv_readdb(path.c_str(), name_ext.c_str(), ',', 3, 3, -1, &skill_parse_row_abradb, false);
|
|
})) {
|
|
return 0;
|
|
}
|
|
|
|
if (!process("IMPROVISED_SONG_DB", 1, root_paths, "skill_improvise_db", [](const std::string& path, const std::string& name_ext) -> bool {
|
|
return sv_readdb(path.c_str(), name_ext.c_str(), ',', 2, 2, -1, &skill_parse_row_improvisedb, false);
|
|
}, "improvise_db")) {
|
|
return 0;
|
|
}
|
|
|
|
if (!process("READING_SPELLBOOK_DB", 1, root_paths, "spellbook_db", [](const std::string& path, const std::string& name_ext) -> bool {
|
|
return sv_readdb(path.c_str(), name_ext.c_str(), ',', 3, 3, -1, &skill_parse_row_spellbookdb, false);
|
|
})) {
|
|
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;
|
|
}
|
|
|
|
skill_txt_data( path_db_mode, path_db );
|
|
if (!process("SKILL_DB", 1, { path_db_mode }, "skill_db", [](const std::string& path, const std::string& name_ext) -> bool {
|
|
return sv_readdb(path.c_str(), name_ext.c_str(), ',', 18, 18, -1, &skill_parse_row_skilldb, false);
|
|
})){
|
|
return 0;
|
|
}
|
|
|
|
skill_txt_data( path_db_import, path_db_import );
|
|
if (!process("SKILL_DB", 1, { path_db_import }, "skill_db", [](const std::string& path, const std::string& name_ext) -> bool {
|
|
return sv_readdb(path.c_str(), name_ext.c_str(), ',', 18, 18, -1, &skill_parse_row_skilldb, false);
|
|
})){
|
|
return 0;
|
|
}
|
|
|
|
// TODO: add implementations ;-)
|
|
|
|
return 0;
|
|
}
|
|
|
|
void do_final(void){
|
|
}
|
|
|
|
bool fileExists( const std::string& path ){
|
|
std::ifstream in;
|
|
|
|
in.open( path );
|
|
|
|
if( in.is_open() ){
|
|
in.close();
|
|
|
|
return true;
|
|
}else{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool askConfirmation( const char* fmt, ... ){
|
|
va_list ap;
|
|
|
|
va_start( ap, fmt );
|
|
|
|
_vShowMessage( MSG_NONE, fmt, ap );
|
|
|
|
va_end( ap );
|
|
|
|
char c = getch();
|
|
|
|
if( c == 'Y' || c == 'y' ){
|
|
return true;
|
|
}else{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// Constant loading functions
|
|
static bool parse_item_constants( const char* path ){
|
|
uint32 lines = 0, count = 0;
|
|
char line[1024];
|
|
|
|
FILE* fp;
|
|
|
|
fp = fopen(path, "r");
|
|
if (fp == NULL) {
|
|
ShowWarning("itemdb_readdb: File not found \"%s\", skipping.\n", path);
|
|
return false;
|
|
}
|
|
|
|
// process rows one by one
|
|
while (fgets(line, sizeof(line), fp))
|
|
{
|
|
char *str[32], *p;
|
|
int i;
|
|
lines++;
|
|
if (line[0] == '/' && line[1] == '/')
|
|
continue;
|
|
memset(str, 0, sizeof(str));
|
|
|
|
p = strstr(line, "//");
|
|
|
|
if (p != nullptr) {
|
|
*p = '\0';
|
|
}
|
|
|
|
p = line;
|
|
while (ISSPACE(*p))
|
|
++p;
|
|
if (*p == '\0')
|
|
continue;// empty line
|
|
for (i = 0; i < 19; ++i)
|
|
{
|
|
str[i] = p;
|
|
p = strchr(p, ',');
|
|
if (p == NULL)
|
|
break;// comma not found
|
|
*p = '\0';
|
|
++p;
|
|
}
|
|
|
|
if (p == NULL)
|
|
{
|
|
ShowError("itemdb_readdb: Insufficient columns in line %d of \"%s\" (item with id %d), skipping.\n", lines, path, atoi(str[0]));
|
|
continue;
|
|
}
|
|
|
|
// Script
|
|
if (*p != '{')
|
|
{
|
|
ShowError("itemdb_readdb: Invalid format (Script column) in line %d of \"%s\" (item with id %d), skipping.\n", lines, path, atoi(str[0]));
|
|
continue;
|
|
}
|
|
str[19] = p + 1;
|
|
p = strstr(p + 1, "},");
|
|
if (p == NULL)
|
|
{
|
|
ShowError("itemdb_readdb: Invalid format (Script column) in line %d of \"%s\" (item with id %d), skipping.\n", lines, path, atoi(str[0]));
|
|
continue;
|
|
}
|
|
*p = '\0';
|
|
p += 2;
|
|
|
|
// OnEquip_Script
|
|
if (*p != '{')
|
|
{
|
|
ShowError("itemdb_readdb: Invalid format (OnEquip_Script column) in line %d of \"%s\" (item with id %d), skipping.\n", lines, path, atoi(str[0]));
|
|
continue;
|
|
}
|
|
str[20] = p + 1;
|
|
p = strstr(p + 1, "},");
|
|
if (p == NULL)
|
|
{
|
|
ShowError("itemdb_readdb: Invalid format (OnEquip_Script column) in line %d of \"%s\" (item with id %d), skipping.\n", lines, path, atoi(str[0]));
|
|
continue;
|
|
}
|
|
*p = '\0';
|
|
p += 2;
|
|
|
|
// OnUnequip_Script (last column)
|
|
if (*p != '{')
|
|
{
|
|
ShowError("itemdb_readdb: Invalid format (OnUnequip_Script column) in line %d of \"%s\" (item with id %d), skipping.\n", lines, path, atoi(str[0]));
|
|
continue;
|
|
}
|
|
str[21] = p;
|
|
p = &str[21][strlen(str[21]) - 2];
|
|
|
|
if (*p != '}') {
|
|
/* lets count to ensure it's not something silly e.g. a extra space at line ending */
|
|
int lcurly = 0, rcurly = 0;
|
|
|
|
for (size_t v = 0; v < strlen(str[21]); v++) {
|
|
if (str[21][v] == '{')
|
|
lcurly++;
|
|
else if (str[21][v] == '}') {
|
|
rcurly++;
|
|
p = &str[21][v];
|
|
}
|
|
}
|
|
|
|
if (lcurly != rcurly) {
|
|
ShowError("itemdb_readdb: Mismatching curly braces in line %d of \"%s\" (item with id %d), skipping.\n", lines, path, atoi(str[0]));
|
|
continue;
|
|
}
|
|
}
|
|
str[21] = str[21] + 1; //skip the first left curly
|
|
*p = '\0'; //null the last right curly
|
|
|
|
uint16 item_id = atoi( str[0] );
|
|
char* name = trim( str[1] );
|
|
|
|
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++;
|
|
}
|
|
|
|
fclose(fp);
|
|
|
|
ShowStatus("Done reading '" CL_WHITE "%u" CL_RESET "' entries in '" CL_WHITE "%s" CL_RESET "'.\n", count, path);
|
|
|
|
return true;
|
|
}
|
|
|
|
static bool parse_mob_constants( char* split[], int columns, int current ){
|
|
uint16 mob_id = atoi( split[0] );
|
|
char* name = trim( split[1] );
|
|
|
|
aegis_mobnames[mob_id] = std::string( name );
|
|
|
|
return true;
|
|
}
|
|
|
|
static bool parse_skill_constants_txt( char* split[], int columns, int current ){
|
|
uint16 skill_id = atoi( split[0] );
|
|
char* name = trim( split[16] );
|
|
|
|
aegis_skillnames[skill_id] = std::string( name );
|
|
|
|
return true;
|
|
}
|
|
|
|
static bool parse_skill_constants_yml(std::string path, std::string filename) {
|
|
YAML::Node rootNode;
|
|
|
|
try {
|
|
rootNode = YAML::LoadFile(path + filename);
|
|
} catch (YAML::Exception &e) {
|
|
ShowError("Failed to read file from '" CL_WHITE "%s%s" CL_RESET "'.\n", path.c_str(), filename.c_str());
|
|
ShowError("%s (Line %d: Column %d)\n", e.msg.c_str(), e.mark.line, e.mark.column);
|
|
return false;
|
|
}
|
|
|
|
uint64 count = 0;
|
|
|
|
for (const YAML::Node &body : rootNode["Body"]) {
|
|
aegis_skillnames[body["Id"].as<uint16>()] = body["Name"].as<std::string>();
|
|
count++;
|
|
}
|
|
|
|
ShowStatus("Done reading '" CL_WHITE "%" PRIu64 CL_RESET "' entries in '" CL_WHITE "%s%s" CL_RESET "'" CL_CLL "\n", count, path.c_str(), filename.c_str());
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Split the string with ':' as separator and put each value for a skilllv
|
|
* @param str: String to split
|
|
* @param val: Array of MAX_SKILL_LEVEL to put value into
|
|
* @return 0:error, x:number of value assign (should be MAX_SKILL_LEVEL)
|
|
*/
|
|
int skill_split_atoi(char *str, int *val) {
|
|
int i;
|
|
|
|
for (i = 0; i < MAX_SKILL_LEVEL; i++) {
|
|
if (!str)
|
|
break;
|
|
val[i] = atoi(str);
|
|
str = strchr(str, ':');
|
|
if (str)
|
|
*str++ = 0;
|
|
}
|
|
|
|
if (i == 0) // No data found.
|
|
return 0;
|
|
|
|
if (i == 1) // Single value, have the whole range have the same value.
|
|
return 1;
|
|
|
|
return i;
|
|
}
|
|
|
|
/**
|
|
* Split string to int by constant value (const.txt) or atoi()
|
|
* @param *str: String input
|
|
* @param *val: Temporary storage
|
|
* @param *delim: Delimiter (for multiple value support)
|
|
* @param min_value: Minimum value. If the splitted value is less or equal than this, will be skipped
|
|
* @param max: Maximum number that can be allocated
|
|
* @return count: Number of success
|
|
*/
|
|
uint8 skill_split_atoi2(char *str, int64 *val, const char *delim, int min_value, uint16 max) {
|
|
uint8 i = 0;
|
|
char *p = strtok(str, delim);
|
|
|
|
while (p != NULL) {
|
|
int64 n = min_value;
|
|
|
|
trim(p);
|
|
|
|
if (ISDIGIT(p[0])) // If using numeric
|
|
n = atoi(p);
|
|
else {
|
|
n = constant_lookup_int(p);
|
|
p = strtok(NULL, delim);
|
|
}
|
|
|
|
if (n > min_value) {
|
|
val[i] = n;
|
|
i++;
|
|
if (i >= max)
|
|
break;
|
|
}
|
|
p = strtok(NULL, delim);
|
|
}
|
|
return i;
|
|
}
|
|
|
|
// Implementation of the conversion functions
|
|
|
|
// Copied and adjusted from guild.cpp
|
|
// <skill id>,<max lv>,<req id1>,<req lv1>,<req id2>,<req lv2>,<req id3>,<req lv3>,<req id4>,<req lv4>,<req id5>,<req lv5>
|
|
static bool guild_read_guildskill_tree_db( char* split[], int columns, int current ){
|
|
uint16 skill_id = (uint16)atoi(split[0]);
|
|
std::string* name = util::umap_find( aegis_skillnames, skill_id );
|
|
|
|
if( name == nullptr ){
|
|
ShowError( "Skill name for skill id %hu is not known.\n", skill_id );
|
|
return false;
|
|
}
|
|
|
|
body << YAML::BeginMap;
|
|
body << YAML::Key << "Id" << YAML::Value << *name;
|
|
body << YAML::Key << "MaxLevel" << YAML::Value << atoi(split[1]);
|
|
|
|
if (atoi(split[2]) > 0) {
|
|
body << YAML::Key << "Required";
|
|
body << YAML::BeginSeq;
|
|
|
|
for (int i = 0, j = 0; i < MAX_GUILD_SKILL_REQUIRE; i++) {
|
|
uint16 required_skill_id = atoi(split[i * 2 + 2]);
|
|
uint16 required_skill_level = atoi(split[i * 2 + 3]);
|
|
|
|
if (required_skill_id == 0 || required_skill_level == 0) {
|
|
continue;
|
|
}
|
|
|
|
std::string* required_name = util::umap_find(aegis_skillnames, required_skill_id);
|
|
|
|
if (required_name == nullptr) {
|
|
ShowError("Skill name for required skill id %hu is not known.\n", required_skill_id);
|
|
return false;
|
|
}
|
|
|
|
body << YAML::BeginMap;
|
|
body << YAML::Key << "Id" << YAML::Value << *required_name;
|
|
body << YAML::Key << "Level" << YAML::Value << required_skill_level;
|
|
body << YAML::EndMap;
|
|
}
|
|
|
|
body << YAML::EndSeq;
|
|
}
|
|
|
|
body << YAML::EndMap;
|
|
|
|
return true;
|
|
}
|
|
|
|
// Copied and adjusted from pet.cpp
|
|
static bool pet_read_db( const char* file ){
|
|
FILE* fp = fopen( file, "r" );
|
|
|
|
if( fp == nullptr ){
|
|
ShowError( "can't read %s\n", file );
|
|
return false;
|
|
}
|
|
|
|
int lines = 0;
|
|
size_t entries = 0;
|
|
char line[1024];
|
|
|
|
while( fgets( line, sizeof(line), fp ) ) {
|
|
char *str[22], *p;
|
|
unsigned k;
|
|
lines++;
|
|
|
|
if(line[0] == '/' && line[1] == '/')
|
|
continue;
|
|
|
|
memset(str, 0, sizeof(str));
|
|
p = line;
|
|
|
|
while( ISSPACE(*p) )
|
|
++p;
|
|
|
|
if( *p == '\0' )
|
|
continue; // empty line
|
|
|
|
for( k = 0; k < 20; ++k ) {
|
|
str[k] = p;
|
|
p = strchr(p,',');
|
|
|
|
if( p == NULL )
|
|
break; // comma not found
|
|
|
|
*p = '\0';
|
|
++p;
|
|
}
|
|
|
|
if( p == NULL ) {
|
|
ShowError("read_petdb: Insufficient columns in line %d, skipping.\n", lines);
|
|
continue;
|
|
}
|
|
|
|
// Pet Script
|
|
if( *p != '{' ) {
|
|
ShowError("read_petdb: Invalid format (Pet Script column) in line %d, skipping.\n", lines);
|
|
continue;
|
|
}
|
|
|
|
str[20] = p;
|
|
p = strstr(p+1,"},");
|
|
|
|
if( p == NULL ) {
|
|
ShowError("read_petdb: Invalid format (Pet Script column) in line %d, skipping.\n", lines);
|
|
continue;
|
|
}
|
|
|
|
p[1] = '\0';
|
|
p += 2;
|
|
|
|
// Equip Script
|
|
if( *p != '{' ) {
|
|
ShowError("read_petdb: Invalid format (Equip Script column) in line %d, skipping.\n", lines);
|
|
continue;
|
|
}
|
|
|
|
str[21] = p;
|
|
|
|
uint16 mob_id = atoi( str[0] );
|
|
std::string* mob_name = util::umap_find( aegis_mobnames, mob_id );
|
|
|
|
if( mob_name == nullptr ){
|
|
ShowWarning( "pet_db reading: Invalid mob-class %hu, pet not read.\n", mob_id );
|
|
continue;
|
|
}
|
|
|
|
body << YAML::BeginMap;
|
|
body << YAML::Key << "Mob" << YAML::Value << *mob_name;
|
|
|
|
uint16 tame_item_id = (uint16)atoi( str[3] );
|
|
|
|
if( tame_item_id > 0 ){
|
|
std::string* tame_item_name = util::umap_find( aegis_itemnames, tame_item_id );
|
|
|
|
if( tame_item_name == nullptr ){
|
|
ShowError( "Item name for item id %hu is not known.\n", tame_item_id );
|
|
return false;
|
|
}
|
|
|
|
body << YAML::Key << "TameItem" << YAML::Value << *tame_item_name;
|
|
}
|
|
|
|
uint16 egg_item_id = (uint16)atoi( str[4] );
|
|
std::string* egg_item_name = util::umap_find( aegis_itemnames, egg_item_id );
|
|
|
|
if( egg_item_name == nullptr ){
|
|
ShowError( "Item name for item id %hu is not known.\n", egg_item_id );
|
|
return false;
|
|
}
|
|
|
|
body << YAML::Key << "EggItem" << YAML::Value << *egg_item_name;
|
|
|
|
uint16 equip_item_id = (uint16)atoi( str[5] );
|
|
|
|
if( equip_item_id > 0 ){
|
|
std::string* equip_item_name = util::umap_find( aegis_itemnames, equip_item_id );
|
|
|
|
if( equip_item_name == nullptr ){
|
|
ShowError( "Item name for item id %hu is not known.\n", equip_item_id );
|
|
return false;
|
|
}
|
|
|
|
body << YAML::Key << "EquipItem" << YAML::Value << *equip_item_name;
|
|
}
|
|
|
|
uint16 food_item_id = (uint16)atoi( str[6] );
|
|
|
|
if( food_item_id > 0 ){
|
|
std::string* food_item_name = util::umap_find( aegis_itemnames, food_item_id );
|
|
|
|
if( food_item_name == nullptr ){
|
|
ShowError( "Item name for item id %hu is not known.\n", food_item_id );
|
|
return false;
|
|
}
|
|
|
|
body << YAML::Key << "FoodItem" << YAML::Value << *food_item_name;
|
|
}
|
|
|
|
body << YAML::Key << "Fullness" << YAML::Value << atoi(str[7]);
|
|
// Default: 60
|
|
if( atoi( str[8] ) != 60 ){
|
|
body << YAML::Key << "HungryDelay" << YAML::Value << atoi(str[8]);
|
|
}
|
|
// Default: 250
|
|
if( atoi( str[11] ) != 250 ){
|
|
body << YAML::Key << "IntimacyStart" << YAML::Value << atoi(str[11]);
|
|
}
|
|
body << YAML::Key << "IntimacyFed" << YAML::Value << atoi(str[9]);
|
|
// Default: -100
|
|
if( atoi( str[10] ) != 100 ){
|
|
body << YAML::Key << "IntimacyOverfed" << YAML::Value << -atoi(str[10]);
|
|
}
|
|
// pet_hungry_friendly_decrease battle_conf
|
|
//body << YAML::Key << "IntimacyHungry" << YAML::Value << -5;
|
|
// Default: -20
|
|
if( atoi( str[12] ) != 20 ){
|
|
body << YAML::Key << "IntimacyOwnerDie" << YAML::Value << -atoi(str[12]);
|
|
}
|
|
body << YAML::Key << "CaptureRate" << YAML::Value << atoi(str[13]);
|
|
// Default: true
|
|
if( atoi( str[15] ) == 0 ){
|
|
body << YAML::Key << "SpecialPerformance" << YAML::Value << "false";
|
|
}
|
|
body << YAML::Key << "AttackRate" << YAML::Value << atoi(str[17]);
|
|
body << YAML::Key << "RetaliateRate" << YAML::Value << atoi(str[18]);
|
|
body << YAML::Key << "ChangeTargetRate" << YAML::Value << atoi(str[19]);
|
|
|
|
if( *str[21] ){
|
|
body << YAML::Key << "Script" << YAML::Value << YAML::Literal << str[21];
|
|
}
|
|
|
|
if( *str[20] ){
|
|
body << YAML::Key << "SupportScript" << YAML::Value << YAML::Literal << str[20];
|
|
}
|
|
|
|
body << YAML::EndMap;
|
|
entries++;
|
|
}
|
|
|
|
fclose(fp);
|
|
ShowStatus("Done reading '" CL_WHITE "%d" CL_RESET "' pets in '" CL_WHITE "%s" CL_RESET "'.\n", entries, file );
|
|
|
|
return true;
|
|
}
|
|
|
|
// Copied and adjusted from skill.cpp
|
|
static bool skill_parse_row_magicmushroomdb(char* split[], int column, int current)
|
|
{
|
|
uint16 skill_id = atoi(split[0]);
|
|
std::string *skill_name = util::umap_find(aegis_skillnames, skill_id);
|
|
|
|
if (skill_name == nullptr) {
|
|
ShowError("Skill name for Magic Mushroom skill ID %hu is not known.\n", skill_id);
|
|
return false;
|
|
}
|
|
|
|
body << YAML::BeginMap;
|
|
body << YAML::Key << "Skill" << YAML::Value << *skill_name;
|
|
body << YAML::EndMap;
|
|
|
|
return true;
|
|
}
|
|
|
|
// Copied and adjusted from skill.cpp
|
|
static bool skill_parse_row_abradb(char* split[], int columns, int current)
|
|
{
|
|
uint16 skill_id = atoi(split[0]);
|
|
std::string *skill_name = util::umap_find(aegis_skillnames, skill_id);
|
|
|
|
if (skill_name == nullptr) {
|
|
ShowError("Skill name for Abra skill ID %hu is not known.\n", skill_id);
|
|
return false;
|
|
}
|
|
|
|
body << YAML::BeginMap;
|
|
body << YAML::Key << "Skill" << YAML::Value << *skill_name;
|
|
|
|
int arr[MAX_SKILL_LEVEL];
|
|
int arr_size = skill_split_atoi(split[2], arr);
|
|
|
|
if (arr_size == 1) {
|
|
if (arr[0] != 500)
|
|
body << YAML::Key << "Probability" << YAML::Value << arr[0];
|
|
} else {
|
|
body << YAML::Key << "Probability";
|
|
body << YAML::BeginSeq;
|
|
|
|
for (int i = 0; i < arr_size; i++) {
|
|
if (arr[i] > 0) {
|
|
body << YAML::BeginMap;
|
|
body << YAML::Key << "Level" << YAML::Value << i + 1;
|
|
body << YAML::Key << "Probability" << YAML::Value << arr[i];
|
|
body << YAML::EndMap;
|
|
}
|
|
}
|
|
|
|
body << YAML::EndSeq;
|
|
}
|
|
|
|
body << YAML::EndMap;
|
|
|
|
return true;
|
|
}
|
|
|
|
// Copied and adjusted from skill.cpp
|
|
static bool skill_parse_row_improvisedb(char* split[], int columns, int current)
|
|
{
|
|
uint16 skill_id = atoi(split[0]);
|
|
std::string *skill_name = util::umap_find(aegis_skillnames, skill_id);
|
|
|
|
if (skill_name == nullptr) {
|
|
ShowError("Skill name for Improvised Song skill ID %hu is not known.\n", skill_id);
|
|
return false;
|
|
}
|
|
|
|
body << YAML::BeginMap;
|
|
body << YAML::Key << "Skill" << YAML::Value << *skill_name;
|
|
body << YAML::Key << "Probability" << YAML::Value << atoi(split[1]) / 10;
|
|
body << YAML::EndMap;
|
|
|
|
return true;
|
|
}
|
|
|
|
// Copied and adjusted from skill.cpp
|
|
static bool skill_parse_row_spellbookdb(char* split[], int columns, int current)
|
|
{
|
|
uint16 skill_id = atoi(split[0]);
|
|
std::string *skill_name = util::umap_find(aegis_skillnames, skill_id);
|
|
|
|
if (skill_name == nullptr) {
|
|
ShowError("Skill name for Spell Book skill ID %hu is not known.\n", skill_id);
|
|
return false;
|
|
}
|
|
|
|
uint16 nameid = atoi(split[2]);
|
|
std::string *book_name = util::umap_find(aegis_itemnames, nameid);
|
|
|
|
if (book_name == nullptr) {
|
|
ShowError("Book name for item ID %hu is not known.\n", nameid);
|
|
return false;
|
|
}
|
|
|
|
body << YAML::BeginMap;
|
|
body << YAML::Key << "Skill" << YAML::Value << *skill_name;
|
|
body << YAML::Key << "Book" << YAML::Value << *book_name;
|
|
body << YAML::Key << "PreservePoints" << YAML::Value << atoi(split[1]);
|
|
body << YAML::EndMap;
|
|
|
|
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::BeginMap;
|
|
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 for id %d is not known.\n", sprite_id);
|
|
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;
|
|
}
|
|
|
|
// skill_db.yml function
|
|
//----------------------
|
|
static bool skill_parse_row_requiredb(char* split[], int columns, int current)
|
|
{
|
|
s_skill_require entry = {};
|
|
|
|
skill_split_atoi(split[1], entry.hp);
|
|
skill_split_atoi(split[2], entry.mhp);
|
|
skill_split_atoi(split[3], entry.sp);
|
|
skill_split_atoi(split[4], entry.hp_rate);
|
|
skill_split_atoi(split[5], entry.sp_rate);
|
|
skill_split_atoi(split[6], entry.zeny);
|
|
|
|
char *p;
|
|
|
|
p = split[7];
|
|
while (p) {
|
|
int l = atoi(p);
|
|
|
|
if (l == 99) { // Any weapon
|
|
entry.weapon = 0;
|
|
break;
|
|
} else
|
|
entry.weapon |= 1 << l;
|
|
p = strchr(p, ':');
|
|
if (!p)
|
|
break;
|
|
p++;
|
|
}
|
|
|
|
p = split[8];
|
|
while (p) {
|
|
int l = atoi(p);
|
|
|
|
if (l == 99) { // Any ammo type
|
|
entry.ammo = AMMO_TYPE_ALL;
|
|
break;
|
|
} else if (l) // 0 stands for no requirement
|
|
entry.ammo |= 1 << l;
|
|
p = strchr(p, ':');
|
|
if (!p)
|
|
break;
|
|
p++;
|
|
}
|
|
|
|
skill_split_atoi(split[9], entry.ammo_qty);
|
|
|
|
if (strcmpi(split[10], "hidden") == 0) entry.state = ST_HIDDEN;
|
|
else if (strcmpi(split[10], "riding") == 0) entry.state = ST_RIDING;
|
|
else if (strcmpi(split[10], "falcon") == 0) entry.state = ST_FALCON;
|
|
else if (strcmpi(split[10], "cart") == 0) entry.state = ST_CART;
|
|
else if (strcmpi(split[10], "shield") == 0) entry.state = ST_SHIELD;
|
|
else if (strcmpi(split[10], "recover_weight_rate") == 0) entry.state = ST_RECOVER_WEIGHT_RATE;
|
|
else if (strcmpi(split[10], "move_enable") == 0) entry.state = ST_MOVE_ENABLE;
|
|
else if (strcmpi(split[10], "water") == 0) entry.state = ST_WATER;
|
|
else if (strcmpi(split[10], "dragon") == 0) entry.state = ST_RIDINGDRAGON;
|
|
else if (strcmpi(split[10], "warg") == 0) entry.state = ST_WUG;
|
|
else if (strcmpi(split[10], "ridingwarg") == 0) entry.state = ST_RIDINGWUG;
|
|
else if (strcmpi(split[10], "mado") == 0) entry.state = ST_MADO;
|
|
else if (strcmpi(split[10], "elementalspirit") == 0) entry.state = ST_ELEMENTALSPIRIT;
|
|
else if (strcmpi(split[10], "elementalspirit2") == 0) entry.state = ST_ELEMENTALSPIRIT2;
|
|
else if (strcmpi(split[10], "peco") == 0) entry.state = ST_PECO;
|
|
else entry.state = ST_NONE; // Unknown or no state
|
|
|
|
trim(split[11]);
|
|
if (split[11][0] != '\0' || atoi(split[11])) {
|
|
int64 require[MAX_SKILL_STATUS_REQUIRE];
|
|
int32 count;
|
|
|
|
if ((count = skill_split_atoi2(split[11], require, ":", SC_STONE, ARRAYLENGTH(require)))) {
|
|
for (int i = 0; i < count; i++) {
|
|
entry.status.push_back((sc_type)require[i]);
|
|
}
|
|
}
|
|
}
|
|
|
|
skill_split_atoi(split[12], entry.spiritball);
|
|
|
|
for (int i = 0; i < MAX_SKILL_ITEM_REQUIRE; i++) {
|
|
if (atoi(split[13 + 2 * i]) > 0) {
|
|
uint16 item_id = atoi(split[13 + 2 * i]);
|
|
std::string *item_name = util::umap_find(aegis_itemnames, item_id);
|
|
|
|
if (item_name == nullptr) {
|
|
ShowError("Item name for item id %hu is not known.\n", item_id);
|
|
return false;
|
|
}
|
|
|
|
entry.itemid[i] = item_id;
|
|
entry.amount[i] = atoi(split[14 + 2 * i]);
|
|
}
|
|
}
|
|
|
|
trim(split[33]);
|
|
if (split[33][0] != '\0' || atoi(split[33])) {
|
|
int64 require[MAX_SKILL_EQUIP_REQUIRE];
|
|
int32 count;
|
|
|
|
if ((count = skill_split_atoi2(split[33], require, ":", 500, ARRAYLENGTH(require)))) {
|
|
for (int i = 0; i < count; i++) {
|
|
if (require[i] > 0)
|
|
entry.eqItem.push_back(static_cast<int32>(require[i]));
|
|
}
|
|
}
|
|
}
|
|
|
|
skill_require.insert({ atoi(split[0]), entry });
|
|
|
|
return true;
|
|
}
|
|
|
|
// skill_db.yml function
|
|
//----------------------
|
|
static bool skill_parse_row_castdb(char* split[], int columns, int current)
|
|
{
|
|
s_skill_db entry = {};
|
|
|
|
skill_split_atoi(split[1], entry.cast);
|
|
skill_split_atoi(split[2], entry.delay);
|
|
skill_split_atoi(split[3], entry.walkdelay);
|
|
skill_split_atoi(split[4], entry.upkeep_time);
|
|
skill_split_atoi(split[5], entry.upkeep_time2);
|
|
skill_split_atoi(split[6], entry.cooldown);
|
|
#ifdef RENEWAL_CAST
|
|
skill_split_atoi(split[7], (int *)entry.fixed_cast);
|
|
#endif
|
|
|
|
skill_cast.insert({ atoi(split[0]), entry });
|
|
|
|
return true;
|
|
}
|
|
|
|
// skill_db.yml function
|
|
//----------------------
|
|
static bool skill_parse_row_castnodexdb(char* split[], int columns, int current)
|
|
{
|
|
s_skill_db entry = {};
|
|
|
|
entry.castnodex = atoi(split[1]);
|
|
if (split[2]) // optional column
|
|
entry.delaynodex = atoi(split[2]);
|
|
|
|
skill_castnodex.insert({ atoi(split[0]), entry });
|
|
|
|
return true;
|
|
}
|
|
|
|
// skill_db.yml function
|
|
//----------------------
|
|
static bool skill_parse_row_unitdb(char* split[], int columns, int current)
|
|
{
|
|
s_skill_unit_csv entry = {};
|
|
|
|
entry.unit_id = (uint16)strtol(split[1], NULL, 16);
|
|
entry.unit_id2 = (uint16)strtol(split[2], NULL, 16);
|
|
skill_split_atoi(split[3], entry.unit_layout_type);
|
|
skill_split_atoi(split[4], entry.unit_range);
|
|
entry.unit_interval = atoi(split[5]);
|
|
entry.target_str = trim(split[6]);
|
|
entry.unit_flag_csv = strtol(split[7], NULL, 16);
|
|
|
|
skill_unit.insert({ atoi(split[0]), entry });
|
|
|
|
return true;
|
|
}
|
|
|
|
// skill_db.yml function
|
|
//----------------------
|
|
static bool skill_parse_row_copyabledb(char* split[], int column, int current)
|
|
{
|
|
s_skill_copyable entry = {};
|
|
int skill_id = -1;
|
|
|
|
trim(split[0]);
|
|
if (ISDIGIT(split[0][0]))
|
|
skill_id = atoi(split[0]);
|
|
else {
|
|
for (const auto &it : aegis_skillnames) {
|
|
if (it.second == split[0])
|
|
skill_id = it.first;
|
|
}
|
|
|
|
if (skill_id == -1) {
|
|
ShowError("Skill %s is unknown.\n", split[0]);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
entry.option = atoi(split[1]);
|
|
entry.req_opt = cap_value(atoi(split[3]), 0, (0x2000) - 1);
|
|
|
|
skill_copyable.insert({ skill_id, entry });
|
|
|
|
return true;
|
|
}
|
|
|
|
// skill_db.yml function
|
|
//----------------------
|
|
static bool skill_parse_row_nonearnpcrangedb(char* split[], int column, int current)
|
|
{
|
|
s_skill_db entry = {};
|
|
int skill_id = -1;
|
|
|
|
trim(split[0]);
|
|
if (ISDIGIT(split[0][0]))
|
|
skill_id = atoi(split[0]);
|
|
else {
|
|
for (const auto &it : aegis_skillnames) {
|
|
if (it.second == split[0])
|
|
skill_id = it.first;
|
|
}
|
|
|
|
if (skill_id == -1) {
|
|
ShowError("Skill %s is unknown.\n", split[0]);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
entry.unit_nonearnpc_range = max(atoi(split[1]), 0);
|
|
entry.unit_nonearnpc_type = (atoi(split[2])) ? cap_value(atoi(split[2]), 1, 15) : 15;
|
|
|
|
skill_nearnpc.insert({ skill_id, entry });
|
|
|
|
return true;
|
|
}
|
|
|
|
static bool isMultiLevel(int arr[]) {
|
|
int count = 0;
|
|
|
|
for (int i = 0; i < MAX_SKILL_LEVEL; i++) {
|
|
if (arr[i] != 0)
|
|
count++;
|
|
}
|
|
|
|
return (count == 0 || count == 1 ? false : true);
|
|
}
|
|
|
|
std::string name2Upper(std::string name) {
|
|
std::transform(name.begin(), name.end(), name.begin(), ::tolower);
|
|
name[0] = toupper(name[0]);
|
|
|
|
for (size_t i = 0; i < name.size(); i++) {
|
|
if (name[i - 1] == '_' || (name[i - 2] == '1' && name[i - 1] == 'h') || (name[i - 2] == '2' && name[i - 1] == 'h'))
|
|
name[i] = toupper(name[i]);
|
|
}
|
|
|
|
return name;
|
|
}
|
|
|
|
// Copied and adjusted from skill.cpp
|
|
static bool skill_parse_row_skilldb(char* split[], int columns, int current) {
|
|
int arr[MAX_SKILL_LEVEL], arr_size, skill_id = atoi(split[0]);
|
|
|
|
body << YAML::BeginMap;
|
|
body << YAML::Key << "Id" << YAML::Value << skill_id;
|
|
body << YAML::Key << "Name" << YAML::Value << trim(split[16]);
|
|
body << YAML::Key << "Description" << YAML::Value << trim(split[17]);
|
|
body << YAML::Key << "MaxLevel" << YAML::Value << atoi(split[7]);
|
|
|
|
if (strcmpi(split[13], "weapon") == 0)
|
|
body << YAML::Key << "Type" << YAML::Value << "Weapon";
|
|
else if (strcmpi(split[13], "magic") == 0)
|
|
body << YAML::Key << "Type" << YAML::Value << "Magic";
|
|
else if (strcmpi(split[13], "misc") == 0)
|
|
body << YAML::Key << "Type" << YAML::Value << "Misc";
|
|
|
|
std::string constant;
|
|
|
|
if (atoi(split[3]) != 0) {
|
|
constant = constant_lookup(atoi(split[3]), "INF_");
|
|
constant.erase(0, 4);
|
|
constant.erase(constant.size() - 6);
|
|
body << YAML::Key << "TargetType" << YAML::Value << name2Upper(constant);
|
|
}
|
|
|
|
uint64 nk_val = strtol(split[5], NULL, 0);
|
|
|
|
if (nk_val) {
|
|
body << YAML::Key << "DamageFlags";
|
|
body << YAML::BeginMap;
|
|
if (nk_val & 0x1)
|
|
body << YAML::Key << "NoDamage" << YAML::Value << "true";
|
|
if (nk_val & 0x2)
|
|
body << YAML::Key << "Splash" << YAML::Value << "true";
|
|
if (nk_val & 0x4)
|
|
body << YAML::Key << "SplashSplit" << YAML::Value << "true";
|
|
if (nk_val & 0x8)
|
|
body << YAML::Key << "IgnoreAtkCard" << YAML::Value << "true";
|
|
if (nk_val & 0x10)
|
|
body << YAML::Key << "IgnoreElement" << YAML::Value << "true";
|
|
if (nk_val & 0x20)
|
|
body << YAML::Key << "IgnoreDefense" << YAML::Value << "true";
|
|
if (nk_val & 0x40)
|
|
body << YAML::Key << "IgnoreFlee" << YAML::Value << "true";
|
|
if (nk_val & 0x80)
|
|
body << YAML::Key << "IgnoreDefCard" << YAML::Value << "true";
|
|
if (nk_val & 0x100)
|
|
body << YAML::Key << "Critical" << YAML::Value << "true";
|
|
|
|
body << YAML::EndMap;
|
|
}
|
|
|
|
uint64 inf2_val = strtol(split[11], nullptr, 0);
|
|
uint64 inf3_val = strtol(split[15], nullptr, 0);
|
|
|
|
if (inf2_val || inf3_val) {
|
|
body << YAML::Key << "Flags";
|
|
body << YAML::BeginMap;
|
|
if (inf2_val & 0x1)
|
|
body << YAML::Key << "IsQuest" << YAML::Value << "true";
|
|
if (inf2_val & 0x2)
|
|
body << YAML::Key << "IsNpc" << YAML::Value << "true";
|
|
if (inf2_val & 0x4)
|
|
body << YAML::Key << "IsWedding" << YAML::Value << "true";
|
|
if (inf2_val & 0x8)
|
|
body << YAML::Key << "IsSpirit" << YAML::Value << "true";
|
|
if (inf2_val & 0x10)
|
|
body << YAML::Key << "IsGuild" << YAML::Value << "true";
|
|
if (inf2_val & 0x20)
|
|
body << YAML::Key << "IsSong" << YAML::Value << "true";
|
|
if (inf2_val & 0x40)
|
|
body << YAML::Key << "IsEnsemble" << YAML::Value << "true";
|
|
if (inf2_val & 0x80)
|
|
body << YAML::Key << "IsTrap" << YAML::Value << "true";
|
|
if (inf2_val & 0x100)
|
|
body << YAML::Key << "TargetSelf" << YAML::Value << "true";
|
|
if (inf2_val & 0x200)
|
|
body << YAML::Key << "NoTargetSelf" << YAML::Value << "true";
|
|
if (inf2_val & 0x400)
|
|
body << YAML::Key << "PartyOnly" << YAML::Value << "true";
|
|
if (inf2_val & 0x800)
|
|
body << YAML::Key << "GuildOnly" << YAML::Value << "true";
|
|
if (inf2_val & 0x1000)
|
|
body << YAML::Key << "NoTargetEnemy" << YAML::Value << "true";
|
|
if (inf2_val & 0x2000)
|
|
body << YAML::Key << "IsAutoShadowSpell" << YAML::Value << "true";
|
|
if (inf2_val & 0x4000)
|
|
body << YAML::Key << "IsChorus" << YAML::Value << "true";
|
|
if (inf2_val & 0x8000)
|
|
body << YAML::Key << "IgnoreBgReduction" << YAML::Value << "true";
|
|
if (inf2_val & 0x10000)
|
|
body << YAML::Key << "IgnoreGvgReduction" << YAML::Value << "true";
|
|
if (inf2_val & 0x20000)
|
|
body << YAML::Key << "DisableNearNpc" << YAML::Value << "true";
|
|
if (inf2_val & 0x40000)
|
|
body << YAML::Key << "TargetTrap" << YAML::Value << "true"; // ?
|
|
|
|
if (inf3_val & 0x1)
|
|
body << YAML::Key << "IgnoreLandProtector" << YAML::Value << "true";
|
|
if (inf3_val & 0x4)
|
|
body << YAML::Key << "AllowWhenHidden" << YAML::Value << "true";
|
|
if (inf3_val & 0x8)
|
|
body << YAML::Key << "AllowWhenPerforming" << YAML::Value << "true";
|
|
if (inf3_val & 0x10)
|
|
body << YAML::Key << "TargetEmperium" << YAML::Value << "true";
|
|
if (inf3_val & 0x20)
|
|
body << YAML::Key << "IgnoreStasis" << YAML::Value << "true";
|
|
if (inf3_val & 0x40)
|
|
body << YAML::Key << "IgnoreKagehumi" << YAML::Value << "true";
|
|
if (inf3_val & 0x80)
|
|
body << YAML::Key << "AlterRangeVulture" << YAML::Value << "true";
|
|
if (inf3_val & 0x100)
|
|
body << YAML::Key << "AlterRangeSnakeEye" << YAML::Value << "true";
|
|
if (inf3_val & 0x200)
|
|
body << YAML::Key << "AlterRangeShadowJump" << YAML::Value << "true";
|
|
if (inf3_val & 0x400)
|
|
body << YAML::Key << "AlterRangeRadius" << YAML::Value << "true";
|
|
if (inf3_val & 0x800)
|
|
body << YAML::Key << "AlterRangeResearchTrap" << YAML::Value << "true";
|
|
if (inf3_val & 0x1000)
|
|
body << YAML::Key << "IgnoreHovering" << YAML::Value << "true";
|
|
if (inf3_val & 0x2000)
|
|
body << YAML::Key << "AllowOnWarg" << YAML::Value << "true";
|
|
if (inf3_val & 0x4000)
|
|
body << YAML::Key << "AllowOnMado" << YAML::Value << "true";
|
|
if (inf3_val & 0x8000)
|
|
body << YAML::Key << "TargetManHole" << YAML::Value << "true";
|
|
if (inf3_val & 0x10000)
|
|
body << YAML::Key << "TargetHidden" << YAML::Value << "true";
|
|
if (inf3_val & 0x20000)
|
|
body << YAML::Key << "IncreaseGloomyDayDamage" << YAML::Value << "true";
|
|
if (inf3_val & 0x40000)
|
|
body << YAML::Key << "IncreaseDanceWithWugDamage" << YAML::Value << "true";
|
|
if (inf3_val & 0x80000)
|
|
body << YAML::Key << "IgnoreWugBite" << YAML::Value << "true";
|
|
if (inf3_val & 0x100000)
|
|
body << YAML::Key << "IgnoreAutoGuard" << YAML::Value << "true";
|
|
if (inf3_val & 0x200000)
|
|
body << YAML::Key << "IgnoreCicada" << YAML::Value << "true";
|
|
|
|
body << YAML::EndMap;
|
|
}
|
|
|
|
memset(arr, 0, sizeof(arr));
|
|
arr_size = skill_split_atoi(split[1], arr);
|
|
|
|
if (arr_size != 0) {
|
|
if (arr_size == 1) {
|
|
if (arr[0] != 0) {
|
|
body << YAML::Key << "Range";
|
|
body << YAML::Value << arr[0];
|
|
}
|
|
} else {
|
|
body << YAML::Key << "Range";
|
|
body << YAML::BeginSeq;
|
|
|
|
for (int i = 0; i < arr_size; i++) {
|
|
body << YAML::BeginMap;
|
|
body << YAML::Key << "Level" << YAML::Value << i + 1;
|
|
body << YAML::Key << "Size" << YAML::Value << arr[i];
|
|
body << YAML::EndMap;
|
|
}
|
|
|
|
body << YAML::EndSeq;
|
|
}
|
|
}
|
|
|
|
if (atoi(split[2]) != 0) {
|
|
constant = constant_lookup(atoi(split[2]), "DMG_");
|
|
constant.erase(0, 4);
|
|
body << YAML::Key << "Hit" << YAML::Value << name2Upper(constant);
|
|
}
|
|
|
|
memset(arr, 0, sizeof(arr));
|
|
arr_size = skill_split_atoi(split[8], arr);
|
|
|
|
if (arr_size != 0) {
|
|
if (arr_size == 1) {
|
|
if (arr[0] != 0) {
|
|
body << YAML::Key << "HitCount";
|
|
body << YAML::Value << arr[0];
|
|
}
|
|
} else {
|
|
body << YAML::Key << "HitCount";
|
|
body << YAML::BeginSeq;
|
|
|
|
for (int i = 0; i < arr_size; i++) {
|
|
body << YAML::BeginMap;
|
|
body << YAML::Key << "Level" << YAML::Value << i + 1;
|
|
body << YAML::Key << "Count" << YAML::Value << arr[i];
|
|
body << YAML::EndMap;
|
|
}
|
|
|
|
body << YAML::EndSeq;
|
|
}
|
|
}
|
|
|
|
memset(arr, 0, sizeof(arr));
|
|
arr_size = skill_split_atoi(split[4], arr);
|
|
|
|
if (arr_size != 0) {
|
|
if (arr_size == 1) {
|
|
if (arr[0] != 0){
|
|
body << YAML::Key << "Element";
|
|
|
|
if (arr[0] == -1)
|
|
body << YAML::Value << "Weapon";
|
|
else if (arr[0] == -2)
|
|
body << YAML::Value << "Endowed";
|
|
else if (arr[0] == -3)
|
|
body << YAML::Value << "Random";
|
|
else {
|
|
constant = constant_lookup(arr[0], "ELE_");
|
|
constant.erase(0, 4);
|
|
body << YAML::Value << name2Upper(constant);
|
|
}
|
|
}
|
|
} else {
|
|
body << YAML::Key << "Element";
|
|
body << YAML::BeginSeq;
|
|
|
|
for (int i = 0; i < arr_size; i++) {
|
|
body << YAML::BeginMap;
|
|
body << YAML::Key << "Level" << YAML::Value << i + 1;
|
|
if (arr[i] == -1)
|
|
body << YAML::Key << "Element" << YAML::Value << "Weapon";
|
|
else if (arr[i] == -2)
|
|
body << YAML::Key << "Element" << YAML::Value << "Endowed";
|
|
else if (arr[i] == -3)
|
|
body << YAML::Key << "Element" << YAML::Value << "Random";
|
|
else {
|
|
constant = constant_lookup(arr[i], "ELE_");
|
|
constant.erase(0, 4);
|
|
body << YAML::Key << "Element" << YAML::Value << name2Upper(constant);
|
|
}
|
|
body << YAML::EndMap;
|
|
}
|
|
|
|
body << YAML::EndSeq;
|
|
}
|
|
}
|
|
|
|
memset(arr, 0, sizeof(arr));
|
|
arr_size = skill_split_atoi(split[6], arr);
|
|
|
|
if (arr_size != 0) {
|
|
if (arr_size == 1) {
|
|
if (arr[0] != 0) {
|
|
body << YAML::Key << "SplashArea";
|
|
body << YAML::Value << arr[0];
|
|
}
|
|
} else {
|
|
body << YAML::Key << "SplashArea";
|
|
body << YAML::BeginSeq;
|
|
|
|
for (int i = 0; i < arr_size; i++) {
|
|
body << YAML::BeginMap;
|
|
body << YAML::Key << "Level" << YAML::Value << i + 1;
|
|
body << YAML::Key << "Area" << YAML::Value << arr[i];
|
|
body << YAML::EndMap;
|
|
}
|
|
|
|
body << YAML::EndSeq;
|
|
}
|
|
}
|
|
|
|
memset(arr, 0, sizeof(arr));
|
|
arr_size = skill_split_atoi(split[12], arr);
|
|
|
|
if (arr_size != 0) {
|
|
if (arr_size == 1) {
|
|
if (arr[0] != 0) {
|
|
body << YAML::Key << "ActiveInstance";
|
|
body << YAML::Value << arr[0];
|
|
}
|
|
} else {
|
|
body << YAML::Key << "ActiveInstance";
|
|
body << YAML::BeginSeq;
|
|
|
|
for (int i = 0; i < arr_size; i++) {
|
|
body << YAML::BeginMap;
|
|
body << YAML::Key << "Level" << YAML::Value << i + 1;
|
|
body << YAML::Key << "Max" << YAML::Value << arr[i];
|
|
body << YAML::EndMap;
|
|
}
|
|
|
|
body << YAML::EndSeq;
|
|
}
|
|
}
|
|
|
|
memset(arr, 0, sizeof(arr));
|
|
arr_size = skill_split_atoi(split[14], arr);
|
|
|
|
if (arr_size != 0) {
|
|
if (arr_size == 1) {
|
|
if (arr[0] != 0) {
|
|
body << YAML::Key << "Knockback";
|
|
body << YAML::Value << arr[0];
|
|
}
|
|
} else {
|
|
body << YAML::Key << "Knockback";
|
|
body << YAML::BeginSeq;
|
|
|
|
for (int i = 0; i < arr_size; i++) {
|
|
body << YAML::BeginMap;
|
|
body << YAML::Key << "Level" << YAML::Value << i + 1;
|
|
body << YAML::Key << "Amount" << YAML::Value << arr[i];
|
|
body << YAML::EndMap;
|
|
}
|
|
|
|
body << YAML::EndSeq;
|
|
}
|
|
}
|
|
|
|
auto it_copyable = skill_copyable.find(skill_id);
|
|
|
|
if (it_copyable != skill_copyable.end()) {
|
|
body << YAML::Key << "CopyFlags";
|
|
body << YAML::BeginMap;
|
|
body << YAML::Key << "Skill";
|
|
body << YAML::BeginMap;
|
|
if (it_copyable->second.option & 1)
|
|
body << YAML::Key << "Plagiarism" << YAML::Value << "true";
|
|
if (it_copyable->second.option & 2)
|
|
body << YAML::Key << "Reproduce" << YAML::Value << "true";
|
|
body << YAML::EndMap;
|
|
|
|
if (it_copyable->second.req_opt > 0) {
|
|
body << YAML::Key << "RemoveRequirement";
|
|
body << YAML::BeginMap;
|
|
if (it_copyable->second.req_opt & 0x1)
|
|
body << YAML::Key << "HpCost" << YAML::Value << "true";
|
|
if (it_copyable->second.req_opt & 0x4)
|
|
body << YAML::Key << "SpCost" << YAML::Value << "true";
|
|
if (it_copyable->second.req_opt & 0x8)
|
|
body << YAML::Key << "HpRateCost" << YAML::Value << "true";
|
|
if (it_copyable->second.req_opt & 0x10)
|
|
body << YAML::Key << "SpRateCost" << YAML::Value << "true";
|
|
if (it_copyable->second.req_opt & 0x2)
|
|
body << YAML::Key << "MaxHpTrigger" << YAML::Value << "true";
|
|
if (it_copyable->second.req_opt & 0x20)
|
|
body << YAML::Key << "ZenyCost" << YAML::Value << "true";
|
|
if (it_copyable->second.req_opt & 0x40)
|
|
body << YAML::Key << "Weapon" << YAML::Value << "true";
|
|
if (it_copyable->second.req_opt & 0x80)
|
|
body << YAML::Key << "Ammo" << YAML::Value << "true";
|
|
if (it_copyable->second.req_opt & 0x100)
|
|
body << YAML::Key << "State" << YAML::Value << "true";
|
|
if (it_copyable->second.req_opt & 0x200)
|
|
body << YAML::Key << "Status" << YAML::Value << "true";
|
|
if (it_copyable->second.req_opt & 0x400)
|
|
body << YAML::Key << "SpiritSphereCost" << YAML::Value << "true";
|
|
if (it_copyable->second.req_opt & 0x800)
|
|
body << YAML::Key << "ItemCost" << YAML::Value << "true";
|
|
if (it_copyable->second.req_opt & 0x1000)
|
|
body << YAML::Key << "Equipment" << YAML::Value << "true";
|
|
body << YAML::EndMap;
|
|
}
|
|
|
|
body << YAML::EndMap;
|
|
}
|
|
|
|
auto it_nearnpc = skill_nearnpc.find(skill_id);
|
|
|
|
if (it_nearnpc != skill_nearnpc.end()) {
|
|
body << YAML::Key << "NoNearNPC";
|
|
body << YAML::BeginMap;
|
|
|
|
if (it_nearnpc->second.unit_nonearnpc_range > 0)
|
|
body << YAML::Key << "AdditionalRange" << YAML::Value << it_nearnpc->second.unit_nonearnpc_range;
|
|
if (it_nearnpc->second.unit_nonearnpc_type > 0) {
|
|
body << YAML::Key << "Type";
|
|
body << YAML::BeginMap;
|
|
if (it_nearnpc->second.unit_nonearnpc_type & 1)
|
|
body << YAML::Key << "WarpPortal" << YAML::Value << "true";
|
|
if (it_nearnpc->second.unit_nonearnpc_type & 2)
|
|
body << YAML::Key << "Shop" << YAML::Value << "true";
|
|
if (it_nearnpc->second.unit_nonearnpc_type & 4)
|
|
body << YAML::Key << "Npc" << YAML::Value << "true";
|
|
if (it_nearnpc->second.unit_nonearnpc_type & 8)
|
|
body << YAML::Key << "Tomb" << YAML::Value << "true";
|
|
body << YAML::EndMap;
|
|
}
|
|
|
|
body << YAML::EndMap;
|
|
}
|
|
|
|
if (strcmpi(split[9], "yes") == 0)
|
|
body << YAML::Key << "CastCancel" << YAML::Value << "true";
|
|
if (atoi(split[10]) != 0)
|
|
body << YAML::Key << "CastDefenseReduction" << YAML::Value << atoi(split[10]);
|
|
|
|
auto it_cast = skill_cast.find(skill_id);
|
|
|
|
if (it_cast != skill_cast.end()) {
|
|
if (!isMultiLevel(it_cast->second.cast)) {
|
|
if (it_cast->second.cast[0] > 0)
|
|
body << YAML::Key << "CastTime" << YAML::Value << it_cast->second.cast[0];
|
|
} else {
|
|
body << YAML::Key << "CastTime";
|
|
body << YAML::BeginSeq;
|
|
|
|
for (size_t i = 0; i < ARRAYLENGTH(it_cast->second.cast); i++) {
|
|
if (it_cast->second.cast[i] > 0) {
|
|
body << YAML::BeginMap;
|
|
body << YAML::Key << "Level" << YAML::Value << i + 1;
|
|
body << YAML::Key << "Time" << YAML::Value << it_cast->second.cast[i];
|
|
body << YAML::EndMap;
|
|
}
|
|
}
|
|
|
|
body << YAML::EndSeq;
|
|
}
|
|
|
|
if (!isMultiLevel(it_cast->second.delay)) {
|
|
if (it_cast->second.delay[0] > 0)
|
|
body << YAML::Key << "AfterCastActDelay" << YAML::Value << it_cast->second.delay[0];
|
|
} else {
|
|
body << YAML::Key << "AfterCastActDelay";
|
|
body << YAML::BeginSeq;
|
|
|
|
for (size_t i = 0; i < ARRAYLENGTH(it_cast->second.delay); i++) {
|
|
if (it_cast->second.delay[i] > 0) {
|
|
body << YAML::BeginMap;
|
|
body << YAML::Key << "Level" << YAML::Value << i + 1;
|
|
body << YAML::Key << "Time" << YAML::Value << it_cast->second.delay[i];
|
|
body << YAML::EndMap;
|
|
}
|
|
}
|
|
|
|
body << YAML::EndSeq;
|
|
}
|
|
|
|
if (!isMultiLevel(it_cast->second.walkdelay)) {
|
|
if (it_cast->second.walkdelay[0] > 0)
|
|
body << YAML::Key << "AfterCastWalkDelay" << YAML::Value << it_cast->second.walkdelay[0];
|
|
} else {
|
|
body << YAML::Key << "AfterCastWalkDelay";
|
|
body << YAML::BeginSeq;
|
|
|
|
for (size_t i = 0; i < ARRAYLENGTH(it_cast->second.walkdelay); i++) {
|
|
if (it_cast->second.walkdelay[i] > 0) {
|
|
body << YAML::BeginMap;
|
|
body << YAML::Key << "Level" << YAML::Value << i + 1;
|
|
body << YAML::Key << "Time" << YAML::Value << it_cast->second.walkdelay[i];
|
|
body << YAML::EndMap;
|
|
}
|
|
}
|
|
|
|
body << YAML::EndSeq;
|
|
}
|
|
|
|
if (!isMultiLevel(it_cast->second.upkeep_time)) {
|
|
if (it_cast->second.upkeep_time[0] != 0)
|
|
body << YAML::Key << "Duration1" << YAML::Value << it_cast->second.upkeep_time[0];
|
|
} else {
|
|
body << YAML::Key << "Duration1";
|
|
body << YAML::BeginSeq;
|
|
|
|
for (size_t i = 0; i < ARRAYLENGTH(it_cast->second.upkeep_time); i++) {
|
|
if (it_cast->second.upkeep_time[i] != 0) {
|
|
body << YAML::BeginMap;
|
|
body << YAML::Key << "Level" << YAML::Value << i + 1;
|
|
body << YAML::Key << "Time" << YAML::Value << it_cast->second.upkeep_time[i];
|
|
body << YAML::EndMap;
|
|
}
|
|
}
|
|
|
|
body << YAML::EndSeq;
|
|
}
|
|
|
|
if (!isMultiLevel(it_cast->second.upkeep_time2)) {
|
|
if (it_cast->second.upkeep_time2[0] != 0)
|
|
body << YAML::Key << "Duration2" << YAML::Value << it_cast->second.upkeep_time2[0];
|
|
} else {
|
|
body << YAML::Key << "Duration2";
|
|
body << YAML::BeginSeq;
|
|
|
|
for (size_t i = 0; i < ARRAYLENGTH(it_cast->second.upkeep_time2); i++) {
|
|
if (it_cast->second.upkeep_time2[i] != 0) {
|
|
body << YAML::BeginMap;
|
|
body << YAML::Key << "Level" << YAML::Value << i + 1;
|
|
body << YAML::Key << "Time" << YAML::Value << it_cast->second.upkeep_time2[i];
|
|
body << YAML::EndMap;
|
|
}
|
|
}
|
|
|
|
body << YAML::EndSeq;
|
|
}
|
|
|
|
if (!isMultiLevel(it_cast->second.cooldown)) {
|
|
if (it_cast->second.cooldown[0] > 0)
|
|
body << YAML::Key << "Cooldown" << YAML::Value << it_cast->second.cooldown[0];
|
|
} else {
|
|
body << YAML::Key << "Cooldown";
|
|
body << YAML::BeginSeq;
|
|
|
|
for (size_t i = 0; i < ARRAYLENGTH(it_cast->second.cooldown); i++) {
|
|
if (it_cast->second.cooldown[i] > 0) {
|
|
body << YAML::BeginMap;
|
|
body << YAML::Key << "Level" << YAML::Value << i + 1;
|
|
body << YAML::Key << "Time" << YAML::Value << it_cast->second.cooldown[i];
|
|
body << YAML::EndMap;
|
|
}
|
|
}
|
|
|
|
body << YAML::EndSeq;
|
|
}
|
|
|
|
#ifdef RENEWAL_CAST
|
|
if (!isMultiLevel(it_cast->second.fixed_cast)) {
|
|
if (it_cast->second.fixed_cast[0] != 0)
|
|
body << YAML::Key << "FixedCastTime" << YAML::Value << it_cast->second.fixed_cast[0];
|
|
} else {
|
|
body << YAML::Key << "FixedCastTime";
|
|
body << YAML::BeginSeq;
|
|
|
|
for (size_t i = 0; i < ARRAYLENGTH(it_cast->second.fixed_cast); i++) {
|
|
if (it_cast->second.fixed_cast[i] != 0) {
|
|
body << YAML::BeginMap;
|
|
body << YAML::Key << "Level" << YAML::Value << i + 1;
|
|
body << YAML::Key << "Time" << YAML::Value << it_cast->second.fixed_cast[i];
|
|
body << YAML::EndMap;
|
|
}
|
|
}
|
|
|
|
body << YAML::EndSeq;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
auto it_castdex = skill_castnodex.find(skill_id);
|
|
|
|
if (it_castdex != skill_castnodex.end()) {
|
|
if (it_castdex->second.castnodex > 0) {
|
|
body << YAML::Key << "CastTimeFlags";
|
|
body << YAML::BeginMap;
|
|
|
|
if (it_castdex->second.castnodex & 1)
|
|
body << YAML::Key << "IgnoreDex" << YAML::Value << "true";
|
|
if (it_castdex->second.castnodex & 2)
|
|
body << YAML::Key << "IgnoreStatus" << YAML::Value << "true";
|
|
if (it_castdex->second.castnodex & 4)
|
|
body << YAML::Key << "IgnoreItemBonus" << YAML::Value << "true";
|
|
|
|
body << YAML::EndMap;
|
|
}
|
|
|
|
if (it_castdex->second.delaynodex > 0) {
|
|
body << YAML::Key << "CastDelayFlags";
|
|
body << YAML::BeginMap;
|
|
|
|
if (it_castdex->second.delaynodex & 1)
|
|
body << YAML::Key << "IgnoreDex" << YAML::Value << "true";
|
|
if (it_castdex->second.delaynodex & 2)
|
|
body << YAML::Key << "IgnoreStatus" << YAML::Value << "true";
|
|
if (it_castdex->second.delaynodex & 4)
|
|
body << YAML::Key << "IgnoreItemBonus" << YAML::Value << "true";
|
|
|
|
body << YAML::EndMap;
|
|
}
|
|
}
|
|
|
|
auto it_req = skill_require.find(skill_id);
|
|
|
|
if (it_req != skill_require.end()) {
|
|
body << YAML::Key << "Requires";
|
|
body << YAML::BeginMap;
|
|
|
|
if (!isMultiLevel(it_req->second.hp)) {
|
|
if (it_req->second.hp[0] > 0)
|
|
body << YAML::Key << "HpCost" << YAML::Value << it_req->second.hp[0];
|
|
} else {
|
|
body << YAML::Key << "HpCost";
|
|
body << YAML::BeginSeq;
|
|
|
|
for (size_t i = 0; i < ARRAYLENGTH(it_req->second.hp); i++) {
|
|
if (it_req->second.hp[i] > 0) {
|
|
body << YAML::BeginMap;
|
|
body << YAML::Key << "Level" << YAML::Value << i + 1;
|
|
body << YAML::Key << "Amount" << YAML::Value << it_req->second.hp[i];
|
|
body << YAML::EndMap;
|
|
}
|
|
}
|
|
|
|
body << YAML::EndSeq;
|
|
}
|
|
|
|
if (!isMultiLevel(it_req->second.sp)) {
|
|
if (it_req->second.sp[0] > 0)
|
|
body << YAML::Key << "SpCost" << YAML::Value << it_req->second.sp[0];
|
|
} else {
|
|
body << YAML::Key << "SpCost";
|
|
body << YAML::BeginSeq;
|
|
|
|
for (size_t i = 0; i < ARRAYLENGTH(it_req->second.sp); i++) {
|
|
if (it_req->second.sp[i] > 0) {
|
|
body << YAML::BeginMap;
|
|
body << YAML::Key << "Level" << YAML::Value << i + 1;
|
|
body << YAML::Key << "Amount" << YAML::Value << it_req->second.sp[i];
|
|
body << YAML::EndMap;
|
|
}
|
|
}
|
|
|
|
body << YAML::EndSeq;
|
|
}
|
|
|
|
if (!isMultiLevel(it_req->second.hp_rate)) {
|
|
if (it_req->second.hp_rate[0] != 0)
|
|
body << YAML::Key << "HpRateCost" << YAML::Value << it_req->second.hp_rate[0];
|
|
} else {
|
|
body << YAML::Key << "HpRateCost";
|
|
body << YAML::BeginSeq;
|
|
|
|
for (size_t i = 0; i < ARRAYLENGTH(it_req->second.hp_rate); i++) {
|
|
if (it_req->second.hp_rate[i] != 0) {
|
|
body << YAML::BeginMap;
|
|
body << YAML::Key << "Level" << YAML::Value << i + 1;
|
|
body << YAML::Key << "Amount" << YAML::Value << it_req->second.hp_rate[i];
|
|
body << YAML::EndMap;
|
|
}
|
|
}
|
|
|
|
body << YAML::EndSeq;
|
|
}
|
|
|
|
if (!isMultiLevel(it_req->second.sp_rate)) {
|
|
if (it_req->second.sp_rate[0] != 0)
|
|
body << YAML::Key << "SpRateCost" << YAML::Value << it_req->second.sp_rate[0];
|
|
} else {
|
|
body << YAML::Key << "SpRateCost";
|
|
body << YAML::BeginSeq;
|
|
|
|
for (size_t i = 0; i < ARRAYLENGTH(it_req->second.sp_rate); i++) {
|
|
if (it_req->second.sp_rate[i] != 0) {
|
|
body << YAML::BeginMap;
|
|
body << YAML::Key << "Level" << YAML::Value << i + 1;
|
|
body << YAML::Key << "Amount" << YAML::Value << it_req->second.sp_rate[i];
|
|
body << YAML::EndMap;
|
|
}
|
|
}
|
|
|
|
body << YAML::EndSeq;
|
|
}
|
|
|
|
if (!isMultiLevel(it_req->second.mhp)) {
|
|
if (it_req->second.mhp[0] > 0)
|
|
body << YAML::Key << "MaxHpTrigger" << YAML::Value << it_req->second.mhp[0];
|
|
} else {
|
|
body << YAML::Key << "MaxHpTrigger";
|
|
body << YAML::BeginSeq;
|
|
|
|
for (size_t i = 0; i < ARRAYLENGTH(it_req->second.mhp); i++) {
|
|
if (it_req->second.mhp[i] > 0) {
|
|
body << YAML::BeginMap;
|
|
body << YAML::Key << "Level" << YAML::Value << i + 1;
|
|
body << YAML::Key << "Amount" << YAML::Value << it_req->second.mhp[i];
|
|
body << YAML::EndMap;
|
|
}
|
|
}
|
|
|
|
body << YAML::EndSeq;
|
|
}
|
|
|
|
if (!isMultiLevel(it_req->second.zeny)) {
|
|
if (it_req->second.zeny[0] > 0)
|
|
body << YAML::Key << "ZenyCost" << YAML::Value << it_req->second.zeny[0];
|
|
} else {
|
|
body << YAML::Key << "ZenyCost";
|
|
body << YAML::BeginSeq;
|
|
|
|
for (size_t i = 0; i < ARRAYLENGTH(it_req->second.zeny); i++) {
|
|
if (it_req->second.zeny[i] > 0) {
|
|
body << YAML::BeginMap;
|
|
body << YAML::Key << "Level" << YAML::Value << i + 1;
|
|
body << YAML::Key << "Amount" << YAML::Value << it_req->second.zeny[i];
|
|
body << YAML::EndMap;
|
|
}
|
|
}
|
|
|
|
body << YAML::EndSeq;
|
|
}
|
|
|
|
if (it_req->second.weapon != 0) {
|
|
body << YAML::Key << "Weapon";
|
|
body << YAML::BeginMap;
|
|
|
|
int temp = it_req->second.weapon;
|
|
|
|
if (temp != 99) { // Not "All"
|
|
for (int i = 0; i < MAX_WEAPON_TYPE_ALL; i++) {
|
|
if (i == MAX_WEAPON_TYPE)
|
|
continue;
|
|
|
|
if (temp & 1 << i) {
|
|
constant = constant_lookup(i, "W_");
|
|
constant.erase(0, 2);
|
|
body << YAML::Key << name2Upper(constant) << YAML::Value << "true";
|
|
temp ^= 1 << i;
|
|
}
|
|
}
|
|
}
|
|
|
|
body << YAML::EndMap;
|
|
}
|
|
|
|
if (it_req->second.ammo != 0) {
|
|
body << YAML::Key << "Ammo";
|
|
body << YAML::BeginMap;
|
|
|
|
int temp = it_req->second.ammo;
|
|
|
|
for (int i = 1; i < MAX_AMMO_TYPE; i++) {
|
|
if (temp & 1 << i) {
|
|
constant = constant_lookup(i, "A_");
|
|
constant.erase(0, 2);
|
|
body << YAML::Key << name2Upper(constant) << YAML::Value << "true";
|
|
temp ^= 1 << i;
|
|
}
|
|
}
|
|
|
|
body << YAML::EndMap;
|
|
}
|
|
if (!isMultiLevel(it_req->second.ammo_qty)) {
|
|
if (it_req->second.ammo_qty[0] > 0)
|
|
body << YAML::Key << "AmmoAmount" << YAML::Value << it_req->second.ammo_qty[0];
|
|
} else {
|
|
body << YAML::Key << "AmmoAmount";
|
|
body << YAML::BeginSeq;
|
|
|
|
for (size_t i = 0; i < ARRAYLENGTH(it_req->second.ammo_qty); i++) {
|
|
if (it_req->second.ammo_qty[i] > 0) {
|
|
body << YAML::BeginMap;
|
|
body << YAML::Key << "Level" << YAML::Value << i + 1;
|
|
body << YAML::Key << "Amount" << YAML::Value << it_req->second.ammo_qty[i];
|
|
body << YAML::EndMap;
|
|
}
|
|
}
|
|
|
|
body << YAML::EndSeq;
|
|
}
|
|
|
|
if (it_req->second.state) {
|
|
constant = constant_lookup(it_req->second.state, "ST_");
|
|
constant.erase(0, 3);
|
|
body << YAML::Key << "State" << YAML::Value << name2Upper(constant);
|
|
}
|
|
|
|
if (it_req->second.status.size() > 0) {
|
|
body << YAML::Key << "Status";
|
|
body << YAML::BeginMap;
|
|
|
|
for (const auto &it : it_req->second.status) {
|
|
constant = constant_lookup(it, "SC_");
|
|
constant.erase(0, 3);
|
|
body << YAML::Key << name2Upper(constant) << YAML::Value << "true";
|
|
}
|
|
|
|
body << YAML::EndMap;
|
|
}
|
|
|
|
if (!isMultiLevel(it_req->second.spiritball)) {
|
|
if (it_req->second.spiritball[0] != 0)
|
|
body << YAML::Key << "SpiritSphereCost" << YAML::Value << it_req->second.spiritball[0];
|
|
} else {
|
|
body << YAML::Key << "SpiritSphereCost";
|
|
body << YAML::BeginSeq;
|
|
|
|
for (size_t i = 0; i < ARRAYLENGTH(it_req->second.spiritball); i++) {
|
|
if (it_req->second.spiritball[i] != 0) {
|
|
body << YAML::BeginMap;
|
|
body << YAML::Key << "Level" << YAML::Value << i + 1;
|
|
body << YAML::Key << "Amount" << YAML::Value << it_req->second.spiritball[i];
|
|
body << YAML::EndMap;
|
|
}
|
|
}
|
|
|
|
body << YAML::EndSeq;
|
|
}
|
|
|
|
if (it_req->second.itemid[0] > 0) {
|
|
body << YAML::Key << "ItemCost";
|
|
body << YAML::BeginSeq;
|
|
|
|
for (uint8 i = 0; i < ARRAYLENGTH(it_req->second.itemid); i++) {
|
|
if (it_req->second.itemid[i] > 0) {
|
|
body << YAML::BeginMap;
|
|
|
|
std::string *item_name = util::umap_find(aegis_itemnames, static_cast<uint16>(it_req->second.itemid[i]));
|
|
|
|
if (item_name == nullptr) {
|
|
ShowError("Item name for item id %hu is not known (itemcost).\n", it_req->second.itemid[i]);
|
|
return false;
|
|
}
|
|
|
|
body << YAML::Key << "Item" << YAML::Value << *item_name;
|
|
body << YAML::Key << "Amount" << YAML::Value << it_req->second.amount[i];
|
|
body << YAML::EndMap;
|
|
}
|
|
}
|
|
|
|
body << YAML::EndSeq;
|
|
}
|
|
|
|
if (it_req->second.eqItem.size() > 0) {
|
|
body << YAML::Key << "Equipment";
|
|
body << YAML::BeginMap;
|
|
|
|
for (const auto &it : it_req->second.eqItem) {
|
|
std::string *item_name = util::umap_find(aegis_itemnames, static_cast<uint16>(it));
|
|
|
|
if (item_name == nullptr) {
|
|
ShowError("Item name for item id %hu is not known (equipment).\n", it);
|
|
return false;
|
|
}
|
|
|
|
body << YAML::Key << *item_name << YAML::Value << "true";
|
|
}
|
|
|
|
body << YAML::EndMap;
|
|
}
|
|
|
|
body << YAML::EndMap;
|
|
}
|
|
|
|
auto it_unit = skill_unit.find(skill_id);
|
|
|
|
if (it_unit != skill_unit.end()) {
|
|
body << YAML::Key << "Unit";
|
|
body << YAML::BeginMap;
|
|
|
|
constant = constant_lookup(it_unit->second.unit_id, "UNT_");
|
|
constant.erase(0, 4);
|
|
body << YAML::Key << "Id" << YAML::Value << name2Upper(constant);
|
|
if (it_unit->second.unit_id2 > 0) {
|
|
constant = constant_lookup(it_unit->second.unit_id2, "UNT_");
|
|
constant.erase(0, 4);
|
|
body << YAML::Key << "AlternateId" << YAML::Value << name2Upper(constant);
|
|
}
|
|
|
|
if (!isMultiLevel(it_unit->second.unit_layout_type)) {
|
|
if (it_unit->second.unit_layout_type[0] != 0)
|
|
body << YAML::Key << "Layout" << YAML::Value << it_unit->second.unit_layout_type[0];
|
|
} else {
|
|
body << YAML::Key << "Layout";
|
|
body << YAML::BeginSeq;
|
|
|
|
for (size_t i = 0; i < ARRAYLENGTH(it_unit->second.unit_layout_type); i++) {
|
|
body << YAML::BeginMap;
|
|
body << YAML::Key << "Level" << YAML::Value << i + 1;
|
|
body << YAML::Key << "Size" << YAML::Value << it_unit->second.unit_layout_type[i];
|
|
body << YAML::EndMap;
|
|
}
|
|
|
|
body << YAML::EndSeq;
|
|
}
|
|
|
|
if (!isMultiLevel(it_unit->second.unit_range)) {
|
|
if (it_unit->second.unit_range[0] != 0)
|
|
body << YAML::Key << "Range" << YAML::Value << it_unit->second.unit_range[0];
|
|
} else {
|
|
body << YAML::Key << "Range";
|
|
body << YAML::BeginSeq;
|
|
|
|
for (size_t i = 0; i < ARRAYLENGTH(it_unit->second.unit_range); i++) {
|
|
body << YAML::BeginMap;
|
|
body << YAML::Key << "Level" << YAML::Value << i + 1;
|
|
body << YAML::Key << "Size" << YAML::Value << it_unit->second.unit_range[i];
|
|
body << YAML::EndMap;
|
|
}
|
|
|
|
body << YAML::EndSeq;
|
|
}
|
|
|
|
if (it_unit->second.unit_interval != 0)
|
|
body << YAML::Key << "Interval" << YAML::Value << it_unit->second.unit_interval;
|
|
|
|
if (it_unit->second.target_str.size() > 0) {
|
|
if (it_unit->second.target_str.compare("noenemy") == 0 || it_unit->second.target_str.compare("friend") == 0)
|
|
body << YAML::Key << "Target" << YAML::Value << "Friend";
|
|
//else if (it_unit->second.target_str.compare("noenemy") == 0) // Same as Friend
|
|
// body << YAML::Key << "Target" << YAML::Value << "NoEnemy";
|
|
else if (it_unit->second.target_str.compare("party") == 0)
|
|
body << YAML::Key << "Target" << YAML::Value << "Party";
|
|
else if (it_unit->second.target_str.compare("ally") == 0)
|
|
body << YAML::Key << "Target" << YAML::Value << "Ally";
|
|
else if (it_unit->second.target_str.compare("guild") == 0)
|
|
body << YAML::Key << "Target" << YAML::Value << "Guild";
|
|
//else if (it_unit->second.target_str.compare("all") == 0)
|
|
// body << YAML::Key << "Target" << YAML::Value << "All";
|
|
else if (it_unit->second.target_str.compare("enemy") == 0)
|
|
body << YAML::Key << "Target" << YAML::Value << "Enemy";
|
|
else if (it_unit->second.target_str.compare("self") == 0)
|
|
body << YAML::Key << "Target" << YAML::Value << "Self";
|
|
else if (it_unit->second.target_str.compare("sameguild") == 0)
|
|
body << YAML::Key << "Target" << YAML::Value << "SameGuild";
|
|
}
|
|
|
|
if (it_unit->second.unit_flag_csv > 0) {
|
|
body << YAML::Key << "Flag";
|
|
body << YAML::BeginMap;
|
|
|
|
if (it_unit->second.unit_flag_csv & 0x1)
|
|
body << YAML::Value << "NoEnemy" << YAML::Value << "true";
|
|
if (it_unit->second.unit_flag_csv & 0x2)
|
|
body << YAML::Value << "NoReiteration" << YAML::Value << "true";
|
|
if (it_unit->second.unit_flag_csv & 0x4)
|
|
body << YAML::Value << "NoFootSet" << YAML::Value << "true";
|
|
if (it_unit->second.unit_flag_csv & 0x8)
|
|
body << YAML::Value << "NoOverlap" << YAML::Value << "true";
|
|
if (it_unit->second.unit_flag_csv & 0x10)
|
|
body << YAML::Value << "PathCheck" << YAML::Value << "true";
|
|
if (it_unit->second.unit_flag_csv & 0x20)
|
|
body << YAML::Value << "NoPc" << YAML::Value << "true";
|
|
if (it_unit->second.unit_flag_csv & 0x40)
|
|
body << YAML::Value << "NoMob" << YAML::Value << "true";
|
|
if (it_unit->second.unit_flag_csv & 0x80)
|
|
body << YAML::Value << "Skill" << YAML::Value << "true";
|
|
if (it_unit->second.unit_flag_csv & 0x100)
|
|
body << YAML::Value << "Dance" << YAML::Value << "true";
|
|
if (it_unit->second.unit_flag_csv & 0x200)
|
|
body << YAML::Value << "Ensemble" << YAML::Value << "true";
|
|
if (it_unit->second.unit_flag_csv & 0x400)
|
|
body << YAML::Value << "Song" << YAML::Value << "true";
|
|
if (it_unit->second.unit_flag_csv & 0x800)
|
|
body << YAML::Value << "DualMode" << YAML::Value << "true";
|
|
if (it_unit->second.unit_flag_csv & 0x1000)
|
|
body << YAML::Value << "NoKnockback" << YAML::Value << "true";
|
|
if (it_unit->second.unit_flag_csv & 0x2000)
|
|
body << YAML::Value << "RangedSingleUnit" << YAML::Value << "true";
|
|
if (it_unit->second.unit_flag_csv & 0x4000)
|
|
body << YAML::Value << "CrazyWeedImmune" << YAML::Value << "true";
|
|
if (it_unit->second.unit_flag_csv & 0x8000)
|
|
body << YAML::Value << "RemovedByFireRain" << YAML::Value << "true";
|
|
if (it_unit->second.unit_flag_csv & 0x10000)
|
|
body << YAML::Value << "KnockbackGroup" << YAML::Value << "true";
|
|
if (it_unit->second.unit_flag_csv & 0x20000)
|
|
body << YAML::Value << "HiddenTrap" << YAML::Value << "true";
|
|
|
|
body << YAML::EndMap;
|
|
}
|
|
|
|
body << YAML::EndMap;
|
|
}
|
|
|
|
body << YAML::EndMap;
|
|
|
|
return true;
|
|
}
|