-
-
Save mtijanic/153271e463918c52a252893a623bbfdc to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "stdio.h" | |
#include "stdlib.h" | |
#include "string.h" | |
#include <algorithm> | |
#include "FileFormats/2da.hpp" | |
#include "FileFormats/Tlk.hpp" | |
static const char *HELP = | |
"NWN ItemProperty table builder\n" | |
"Usage: build_itemproperty_table [OPTIONS]\n" | |
"Options:\n" | |
" -h, --help Print this message\n" | |
" -p, --path=VALUE Path where all the resources can be found\n" | |
" -t, --tlk=NAME Name of custom tlk file\n" | |
" -f, --format=FORMAT output format; supported values: sql, csv, text (default)\n"; | |
struct CFG { | |
std::string path; | |
std::string tlk; | |
enum { SQL, CSV, TEXT } format; | |
} cfg; | |
#define die(format, ...) \ | |
do { \ | |
fprintf(stderr, format " @ %s():%d\n", ##__VA_ARGS__ , __FUNCTION__, __LINE__); \ | |
exit(~0); \ | |
} while(0) | |
void parse_cmdline(int argc, char *argv[]) { | |
/* if (argc < 3) { | |
puts(HELP); | |
exit(0); | |
}*/ | |
const char *fmt = "text"; | |
for (int i = 1; i < argc; i++) { | |
if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) { | |
puts(HELP); | |
exit(0); | |
} | |
if (!strcmp(argv[i], "-p")) | |
cfg.path = argv[++i]; | |
else if (!strcmp(argv[i], "-t")) | |
cfg.tlk = argv[++i]; | |
else if (!strcmp(argv[i], "-f")) | |
fmt = argv[++i]; | |
else { | |
if (!strncmp(argv[i],"--path=",strlen("--path="))) | |
cfg.path = argv[i] + strlen("--path="); | |
else if (!strncmp(argv[i],"--tlk=",strlen("--tlk="))) | |
cfg.tlk = argv[i] + strlen("--tlk="); | |
else if (!strncmp(argv[i],"--format=",strlen("--format="))) | |
fmt = argv[i] + strlen("--format="); | |
else | |
die("Unkown argument %s", argv[i]); | |
} | |
} | |
switch (*fmt) { | |
case 's': cfg.format = CFG::SQL; break; | |
case 'c': cfg.format = CFG::CSV; break; | |
default: cfg.format = CFG::TEXT; break; | |
} | |
if (cfg.path != "") | |
cfg.path += "/"; | |
} | |
FileFormats::TwoDA::Friendly::TwoDA load_2da(const std::string& name) { | |
FileFormats::TwoDA::Raw::TwoDA twoDARaw; | |
auto fullname = cfg.path + name; | |
std::transform(fullname.begin(), fullname.end(), fullname.begin(), ::tolower); | |
if (!FileFormats::TwoDA::Raw::TwoDA::ReadFromFile(fullname.c_str(), &twoDARaw)) | |
die("Failed to load %s", fullname.c_str()); | |
return FileFormats::TwoDA::Friendly::TwoDA(std::move(twoDARaw)); | |
} | |
FileFormats::Tlk::Friendly::Tlk load_tlk(const std::string& name) { | |
FileFormats::Tlk::Raw::Tlk rawTlk; | |
auto fullname = cfg.path + name; | |
std::transform(fullname.begin(), fullname.end(), fullname.begin(), ::tolower); | |
if (!FileFormats::Tlk::Raw::Tlk::ReadFromFile(fullname.c_str(), &rawTlk)) | |
die("Failed to load %s", fullname.c_str()); | |
return FileFormats::Tlk::Friendly::Tlk(std::move(rawTlk)); | |
} | |
std::string tlk_lookup(int strref) { | |
if (strref > 0x1000000) { | |
static auto tlk = load_tlk(cfg.tlk); | |
return tlk[strref - 0x1000000]; | |
} | |
else { | |
static auto tlk = load_tlk("dialog.tlk"); | |
return tlk[strref]; | |
} | |
} | |
int as_int(std::string str) { | |
try { | |
return std::stoi(str); | |
} catch(...) { | |
return -1; | |
} | |
} | |
struct itemproperty { | |
int type; | |
int subtype; | |
int cost; | |
int cost_value; | |
int param; | |
int param_value; | |
std::string type_name; | |
std::string subtype_name; | |
std::string cost_name; | |
std::string param_name; | |
}; | |
std::vector<itemproperty> build_ip_table() { | |
std::vector<itemproperty> iptable; | |
auto itempropdef = load_2da("itempropdef.2da"); | |
auto iprp_costtable = load_2da("iprp_costtable.2da"); | |
auto iprp_paramtable = load_2da("iprp_paramtable.2da"); | |
for (auto &row: itempropdef) { | |
if (row["GameStrRef"] == "****") | |
continue; | |
auto type = row.RowIdx(); | |
auto cost = as_int(row["CostTableResRef"]); | |
auto param = as_int(row["Param1ResRef"]); | |
auto type_name = tlk_lookup(as_int(row["GameStrRef"])); | |
std::vector<std::pair<int, std::string>> valid_subtypes; | |
if (row["SubTypeResRef"] != "****") { | |
auto subtype_2da = load_2da(row["SubTypeResRef"] + ".2da"); | |
for (auto &subtype_row : subtype_2da) { | |
auto strref = as_int(subtype_row["Name"]); | |
if (strref != -1) | |
valid_subtypes.emplace_back(std::make_pair<>(subtype_row.RowIdx(), tlk_lookup(strref))); | |
} | |
} | |
if (valid_subtypes.empty()) | |
valid_subtypes.emplace_back(std::make_pair<>(-1, "")); | |
std::vector<std::pair<int, std::string>> valid_costs; | |
if (cost != -1) { | |
auto cost_2da = load_2da(iprp_costtable[cost]["Name"] + ".2da"); | |
for (auto &cost_row : cost_2da) { | |
auto strref = as_int(cost_row["Name"]); | |
if (strref != -1) | |
valid_costs.emplace_back(std::make_pair<>(cost_row.RowIdx(), tlk_lookup(strref))); | |
} | |
} | |
if (valid_costs.empty()) | |
valid_costs.emplace_back(std::make_pair<>(-1, "")); | |
std::vector<std::pair<int, std::string>> valid_params; | |
if (param != -1) { | |
auto param_2da = load_2da(iprp_paramtable[param]["TableResRef"] + ".2da"); | |
for (auto ¶m_row : param_2da) { | |
auto strref = as_int(param_row["Name"]); | |
if (strref != -1) | |
valid_params.emplace_back(std::make_pair<>(param_row.RowIdx(), tlk_lookup(strref))); | |
} | |
} | |
if (valid_params.empty()) | |
valid_params.emplace_back(std::make_pair<>(-1, "")); | |
for (auto &subtype: valid_subtypes) { | |
for (auto &cost_value: valid_costs) { | |
for (auto ¶m_value: valid_params) { | |
itemproperty ip; | |
ip.type = type; | |
ip.subtype = subtype.first; | |
ip.cost = cost; | |
ip.cost_value = cost_value.first; | |
ip.param = param; | |
ip.param_value = param_value.first; | |
ip.type_name = type_name; | |
ip.subtype_name = subtype.second; | |
ip.cost_name = cost_value.second; | |
ip.param_name = param_value.second; | |
iptable.emplace_back(ip); | |
} | |
} | |
} | |
} | |
return std::move(iptable); | |
} | |
void print_ip(const itemproperty& ip) { | |
printf(" % 8d % 8d % 8d % 8d % 8d % 8d : %s %s %s %s\n", | |
ip.type, ip.subtype, ip.cost, ip.cost_value, ip.param, ip.param_value, | |
ip.type_name.c_str(), ip.subtype_name.c_str(), ip.cost_name.c_str(), ip.param_name.c_str()); | |
} | |
int main(int argc, char** argv) { | |
parse_cmdline(argc, argv); | |
auto table = build_ip_table(); | |
for (auto &ip: table) | |
print_ip(ip); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment