356 lines
8.2 KiB
C++
356 lines
8.2 KiB
C++
#include "Contents/Items/ItemInfo.h"
|
|
#include "Contents/Items/ItemNaming.h"
|
|
#include "Contents/MessageTable.h"
|
|
#include "Contents/PlayerNameDictionary.h"
|
|
|
|
#include <cstdlib>
|
|
#include <cstring>
|
|
|
|
namespace {
|
|
// OFFSET: 0x006D8810
|
|
// FUNCTION: fn_06597
|
|
bool Equipment(const ItemInfo& item) {
|
|
switch (item.unknown_0000[0]) {
|
|
case 4:
|
|
case 5:
|
|
case 8:
|
|
case 9:
|
|
case 11:
|
|
case 12:
|
|
case 13:
|
|
case 14:
|
|
case 15:
|
|
case 21:
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// INLINED
|
|
void CardIds(const ItemInfo& item, int (&ids)[4]) {
|
|
std::memcpy(ids, item.unknown_001C, sizeof(ids));
|
|
}
|
|
|
|
// INLINED
|
|
int Copy(char* output, int capacity, const char* text) {
|
|
const int error = strncpy_s(output, capacity, text ? text : " ", _TRUNCATE);
|
|
return error == 0 || error == 80 ? (output ? static_cast<int>(strnlen(output, capacity)) : 0) : 0;
|
|
}
|
|
}
|
|
|
|
// INLINED
|
|
const char* ItemNaming::Message(int id) const {
|
|
return LookupMessage(id, this->languagePrefix, this->service, this->language);
|
|
}
|
|
|
|
// OFFSET: 0x006D77E0
|
|
// FUNCTION: fn_06595
|
|
bool ItemNaming::HasCards(const ItemInfo& item) const {
|
|
int ids[4];
|
|
CardIds(item, ids);
|
|
const bool first = this->cards.contains(ids[0]);
|
|
const unsigned id = static_cast<unsigned>(std::atoi(item.itemId.c_str()));
|
|
|
|
if (id - 9001u <= 498 || id - 10000u <= 999 || ids[0] == 254 || ids[0] == 255 || !Equipment(item)) {
|
|
return first;
|
|
}
|
|
|
|
return first || this->cards.contains(ids[1]) || this->cards.contains(ids[2]) || this->cards.contains(ids[3]);
|
|
}
|
|
|
|
// OFFSET: 0x006D5780
|
|
// FUNCTION: fn_06577
|
|
int ItemNaming::Grade(const ItemInfo& item, char* output, int& capacity, unsigned char consume) const {
|
|
const char grade[2] = {item.unknown_0088 >= 1 && item.unknown_0088 <= 4 ? "DCBA"[item.unknown_0088 - 1] : '\0', '\0'};
|
|
const int bytes = _snprintf_s(output, capacity, _TRUNCATE, "[%s] ", grade);
|
|
if (bytes <= 0) {
|
|
return 0;
|
|
}
|
|
|
|
if (consume) {
|
|
capacity -= bytes;
|
|
}
|
|
|
|
return bytes;
|
|
}
|
|
|
|
// OFFSET: 0x006D6C10
|
|
// FUNCTION: fn_06585
|
|
int ItemNaming::Creator(const ItemInfo& item, char* output, int& capacity, unsigned char consume) {
|
|
int ids[4];
|
|
CardIds(item, ids);
|
|
std::string name = this->players.Lookup(static_cast<unsigned>(ids[2]) + (static_cast<unsigned>(ids[3]) << 16));
|
|
|
|
if (name.empty()) {
|
|
name = this->Message(581);
|
|
}
|
|
|
|
const int bytes = Copy(output, capacity, name.c_str());
|
|
if (consume) {
|
|
capacity -= bytes;
|
|
}
|
|
|
|
return bytes;
|
|
}
|
|
|
|
// OFFSET: 0x006D6F50
|
|
// FUNCTION: fn_06588
|
|
int ItemNaming::Prefixes(const ItemInfo& item, char* output, int& capacity, unsigned char consume) const {
|
|
int ids[4];
|
|
CardIds(item, ids);
|
|
int remaining = capacity;
|
|
char* cursor = output;
|
|
|
|
for (int index = 0; index < 4; ++index) {
|
|
if (ids[index] <= 0) {
|
|
continue;
|
|
}
|
|
|
|
const auto card = this->cards.find(ids[index]);
|
|
if (card == this->cards.end() || !card->second.prefix || !*card->second.prefix) {
|
|
continue;
|
|
}
|
|
|
|
int count = 1;
|
|
|
|
for (int next = index + 1; next < 4; ++next) {
|
|
if (ids[next] == ids[index]) {
|
|
ids[next] = 0;
|
|
++count;
|
|
}
|
|
}
|
|
|
|
if (count >= 2) {
|
|
const int bytes = _snprintf_s(cursor, remaining, _TRUNCATE, "%s ", this->Message(444 + count));
|
|
if (bytes > 0) {
|
|
cursor += bytes;
|
|
remaining -= bytes;
|
|
}
|
|
}
|
|
|
|
const int bytes = _snprintf_s(cursor, remaining, _TRUNCATE, "%s ", card->second.prefix);
|
|
if (bytes > 0) {
|
|
cursor += bytes;
|
|
remaining -= bytes;
|
|
}
|
|
}
|
|
|
|
const int bytes = static_cast<int>(cursor - output);
|
|
if (consume) {
|
|
capacity -= bytes;
|
|
}
|
|
|
|
return bytes;
|
|
}
|
|
|
|
// OFFSET: 0x006D6DB0
|
|
// FUNCTION: fn_06587
|
|
int ItemNaming::Suffixes(const ItemInfo& item, char* output, int& capacity, unsigned char consume) const {
|
|
int ids[4];
|
|
CardIds(item, ids);
|
|
int remaining = capacity;
|
|
char* cursor = output;
|
|
|
|
for (int index = 0; index < 4; ++index) {
|
|
if (ids[index] <= 0) {
|
|
continue;
|
|
}
|
|
|
|
const auto card = this->cards.find(ids[index]);
|
|
if (card == this->cards.end() || !card->second.suffix || !*card->second.suffix) {
|
|
continue;
|
|
}
|
|
|
|
int count = 1;
|
|
|
|
for (int next = index + 1; next < 4; ++next) {
|
|
if (ids[next] == ids[index]) {
|
|
ids[next] = 0;
|
|
++count;
|
|
}
|
|
}
|
|
|
|
int bytes = _snprintf_s(cursor, remaining, _TRUNCATE, " %s", card->second.suffix);
|
|
if (bytes > 0) {
|
|
cursor += bytes;
|
|
remaining -= bytes;
|
|
}
|
|
|
|
if (count >= 2) {
|
|
bytes = _snprintf_s(cursor, remaining, _TRUNCATE, " %s", this->Message(444 + count));
|
|
if (bytes > 0) {
|
|
cursor += bytes;
|
|
remaining -= bytes;
|
|
}
|
|
}
|
|
}
|
|
|
|
const int bytes = static_cast<int>(cursor - output);
|
|
if (consume) {
|
|
capacity -= bytes;
|
|
}
|
|
|
|
return bytes;
|
|
}
|
|
|
|
// OFFSET: 0x006D76E0
|
|
// FUNCTION: fn_06593
|
|
int ItemNaming::Slots(const ItemInfo& item, char* output, int& capacity, unsigned char consume) {
|
|
const int slots = this->descriptions.Find(std::atoi(item.itemId.c_str())).slots;
|
|
if (slots == 0) {
|
|
return 0;
|
|
}
|
|
|
|
const int bytes = _snprintf_s(output, capacity, _TRUNCATE, " [%d]", slots);
|
|
if (bytes <= 0) {
|
|
return 0;
|
|
}
|
|
|
|
if (consume) {
|
|
capacity -= bytes;
|
|
}
|
|
|
|
return bytes;
|
|
}
|
|
|
|
// OFFSET: 0x006D59A0
|
|
// FUNCTION: fn_06581
|
|
std::string ItemNaming::DisplayName(const ItemInfo& item, unsigned char detailed) {
|
|
char text[128] = {};
|
|
int capacity = 128;
|
|
std::string result;
|
|
result.reserve(150);
|
|
const auto append = [&](int bytes) {
|
|
if (bytes > 0) {
|
|
result += text;
|
|
}
|
|
};
|
|
const int id = std::atoi(item.itemId.c_str());
|
|
ITEM_DESC& descriptor = this->descriptions.Find(id);
|
|
|
|
if (item.identified != 1) {
|
|
append(Copy(text, capacity, descriptor.unidentifiedName));
|
|
return result;
|
|
}
|
|
|
|
int cards[4];
|
|
CardIds(item, cards);
|
|
if ((static_cast<unsigned>(id) - 9001u <= 498 || static_cast<unsigned>(id) - 10000u <= 999) && cards[3] == 1) {
|
|
append(Copy(text, capacity, this->Message(756)));
|
|
append(Copy(text, capacity, descriptor.identifiedName));
|
|
return result;
|
|
}
|
|
|
|
const auto refine = [&]() {
|
|
const int value = item.unknown_0060;
|
|
if (value > 0) {
|
|
append(_snprintf_s(text, sizeof(text), _TRUNCATE, "+%d ", value));
|
|
}
|
|
|
|
if (item.unknown_0088 > 0) {
|
|
append(this->Grade(item, text, capacity, 0));
|
|
}
|
|
};
|
|
const auto name = [&]() { append(Copy(text, capacity, descriptor.identifiedName)); };
|
|
const auto element = [&]() {
|
|
const unsigned value = item.unknown_001C[4];
|
|
int message = 0;
|
|
|
|
switch (value) {
|
|
case 0:
|
|
message = id == 2634 || id == 2635 ? 2976 : 450;
|
|
break;
|
|
case 1:
|
|
message = 452;
|
|
break;
|
|
case 2:
|
|
message = 454;
|
|
break;
|
|
case 3:
|
|
message = 451;
|
|
break;
|
|
case 4:
|
|
message = 453;
|
|
break;
|
|
}
|
|
|
|
if (message) {
|
|
append(Copy(text, capacity, this->Message(message)));
|
|
}
|
|
};
|
|
const auto star = [&]() {
|
|
int message = 0;
|
|
|
|
switch (item.unknown_001C[5]) {
|
|
case 5:
|
|
message = 459;
|
|
break;
|
|
case 10:
|
|
message = 460;
|
|
break;
|
|
case 15:
|
|
message = 461;
|
|
break;
|
|
}
|
|
|
|
if (message) {
|
|
append(Copy(text, capacity, this->Message(message)));
|
|
}
|
|
};
|
|
|
|
if (cards[0] == 254 && cards[1] == 0) {
|
|
refine();
|
|
if (this->service != 12 && this->service != 14) {
|
|
append(this->Creator(item, text, capacity, 0));
|
|
element();
|
|
name();
|
|
} else {
|
|
name();
|
|
element();
|
|
append(this->Creator(item, text, capacity, 0));
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
if (!Equipment(item) && detailed == 0) {
|
|
name();
|
|
return result;
|
|
}
|
|
|
|
refine();
|
|
if (this->HasCards(item)) {
|
|
append(this->Prefixes(item, text, capacity, 0));
|
|
name();
|
|
append(this->Suffixes(item, text, capacity, 0));
|
|
append(this->Slots(item, text, capacity, 0));
|
|
|
|
return result;
|
|
}
|
|
|
|
if (cards[0] != 254 && cards[0] != 255) {
|
|
name();
|
|
append(this->Slots(item, text, capacity, 0));
|
|
return result;
|
|
}
|
|
|
|
if (this->service == 12) {
|
|
name();
|
|
element();
|
|
star();
|
|
append(this->Creator(item, text, capacity, 0));
|
|
} else if (this->service == 14) {
|
|
star();
|
|
name();
|
|
element();
|
|
append(this->Creator(item, text, capacity, 0));
|
|
} else {
|
|
star();
|
|
append(this->Creator(item, text, capacity, 0));
|
|
element();
|
|
name();
|
|
}
|
|
|
|
return result;
|
|
}
|