Browse Source

Added support for mapping IDs for item types

pull/8137/head
Andrettin 7 months ago committed by Anders Jenbo
parent
commit
7d1aebd91b
  1. 17
      Source/itemdat.cpp
  2. 6
      Source/itemdat.h
  3. 28
      Source/loadsave.cpp
  4. 6
      Source/lua/modules/items.cpp

17
Source/itemdat.cpp

@ -24,6 +24,9 @@ namespace devilution {
/** Contains the data related to each item ID. */ /** Contains the data related to each item ID. */
std::vector<ItemData> AllItemsList; std::vector<ItemData> AllItemsList;
/** Contains item mapping IDs, with item indices assigned to them. This is used for loading saved games. */
ankerl::unordered_dense::map<int32_t, int16_t> ItemMappingIdsToIndices;
/** Contains the mapping between unique base item ID strings and indices, used for parsing additional item data. */ /** Contains the mapping between unique base item ID strings and indices, used for parsing additional item data. */
ankerl::unordered_dense::map<std::string, int8_t> AdditionalUniqueBaseItemStringsToIndices; ankerl::unordered_dense::map<std::string, int8_t> AdditionalUniqueBaseItemStringsToIndices;
@ -548,10 +551,11 @@ tl::expected<goodorevil, std::string> ParseAffixAlignment(std::string_view value
} // namespace } // namespace
void LoadItemDatFromFile(DataFile &dataFile, std::string_view filename) void LoadItemDatFromFile(DataFile &dataFile, std::string_view filename, int32_t baseMappingId)
{ {
dataFile.skipHeaderOrDie(filename); dataFile.skipHeaderOrDie(filename);
int32_t currentMappingId = baseMappingId;
AllItemsList.reserve(AllItemsList.size() + dataFile.numRecords()); AllItemsList.reserve(AllItemsList.size() + dataFile.numRecords());
for (DataFileRecord record : dataFile) { for (DataFileRecord record : dataFile) {
RecordReader reader { record, filename }; RecordReader reader { record, filename };
@ -579,6 +583,14 @@ void LoadItemDatFromFile(DataFile &dataFile, std::string_view filename)
reader.read("spell", item.iSpell, ParseSpellId); reader.read("spell", item.iSpell, ParseSpellId);
reader.readBool("usable", item.iUsable); reader.readBool("usable", item.iUsable);
reader.readInt("value", item.iValue); reader.readInt("value", item.iValue);
item.iMappingId = currentMappingId;
const auto [it, inserted] = ItemMappingIdsToIndices.emplace(item.iMappingId, static_cast<int16_t>(AllItemsList.size()) - 1);
if (!inserted) {
DisplayFatalErrorAndExit("Adding Item Failed", fmt::format("An item already exists for mapping ID {}.", item.iMappingId));
}
++currentMappingId;
} }
AllItemsList.shrink_to_fit(); AllItemsList.shrink_to_fit();
} }
@ -592,7 +604,8 @@ void LoadItemDat()
AllItemsList.clear(); AllItemsList.clear();
AdditionalUniqueBaseItemStringsToIndices.clear(); AdditionalUniqueBaseItemStringsToIndices.clear();
LoadItemDatFromFile(dataFile, filename); ItemMappingIdsToIndices.clear();
LoadItemDatFromFile(dataFile, filename, 0);
LuaEvent("ItemDataLoaded"); LuaEvent("ItemDataLoaded");
} }

6
Source/itemdat.h

@ -80,7 +80,7 @@ enum _item_indexes : int16_t { // TODO defines all indexes in AllItemsList
IDI_SORCERER_DIABLO, IDI_SORCERER_DIABLO,
IDI_ARENAPOT, IDI_ARENAPOT,
IDI_LAST = IDI_ARENAPOT, IDI_NUM_DEFAULT_ITEMS,
IDI_NONE = -1, IDI_NONE = -1,
}; };
@ -511,6 +511,7 @@ struct ItemData {
SpellID iSpell; SpellID iSpell;
bool iUsable; bool iUsable;
uint16_t iValue; uint16_t iValue;
int32_t iMappingId;
}; };
enum item_effect_type : int8_t { enum item_effect_type : int8_t {
@ -647,12 +648,13 @@ struct UniqueItem {
}; };
extern DVL_API_FOR_TEST std::vector<ItemData> AllItemsList; extern DVL_API_FOR_TEST std::vector<ItemData> AllItemsList;
extern ankerl::unordered_dense::map<int32_t, int16_t> ItemMappingIdsToIndices;
extern std::vector<PLStruct> ItemPrefixes; extern std::vector<PLStruct> ItemPrefixes;
extern std::vector<PLStruct> ItemSuffixes; extern std::vector<PLStruct> ItemSuffixes;
extern DVL_API_FOR_TEST std::vector<UniqueItem> UniqueItems; extern DVL_API_FOR_TEST std::vector<UniqueItem> UniqueItems;
extern ankerl::unordered_dense::map<int32_t, int32_t> UniqueItemMappingIdsToIndices; extern ankerl::unordered_dense::map<int32_t, int32_t> UniqueItemMappingIdsToIndices;
void LoadItemDatFromFile(DataFile &dataFile, std::string_view filename); void LoadItemDatFromFile(DataFile &dataFile, std::string_view filename, int32_t baseMappingId);
void LoadUniqueItemDatFromFile(DataFile &dataFile, std::string_view filename, int32_t baseMappingId); void LoadUniqueItemDatFromFile(DataFile &dataFile, std::string_view filename, int32_t baseMappingId);
void LoadItemData(); void LoadItemData();

28
Source/loadsave.cpp

@ -352,13 +352,21 @@ struct LevelConversionData {
item._iMinDex = file.NextLE<int8_t>(); item._iMinDex = file.NextLE<int8_t>();
file.Skip(1); // Alignment file.Skip(1); // Alignment
item._iStatFlag = file.NextBool32(); item._iStatFlag = file.NextBool32();
item.IDidx = static_cast<_item_indexes>(file.NextLE<int32_t>());
if (gbIsSpawn) { int32_t itemMappingId = file.NextLE<int32_t>();
item.IDidx = RemapItemIdxFromSpawn(item.IDidx); if (gbIsSpawn && itemMappingId < IDI_NUM_DEFAULT_ITEMS) {
itemMappingId = RemapItemIdxFromSpawn(static_cast<_item_indexes>(itemMappingId));
}
if (!gbIsHellfireSaveGame && itemMappingId < IDI_NUM_DEFAULT_ITEMS) {
itemMappingId = RemapItemIdxFromDiablo(static_cast<_item_indexes>(itemMappingId));
} }
if (!gbIsHellfireSaveGame) { const auto findIt = ItemMappingIdsToIndices.find(itemMappingId);
item.IDidx = RemapItemIdxFromDiablo(item.IDidx); if (findIt == ItemMappingIdsToIndices.end()) {
return false;
} }
const _item_indexes itemIndex = static_cast<_item_indexes>(findIt->second);
item.IDidx = itemIndex;
item.dwBuff = file.NextLE<uint32_t>(); item.dwBuff = file.NextLE<uint32_t>();
if (gbIsHellfireSaveGame) if (gbIsHellfireSaveGame)
item._iDamAcFlags = static_cast<ItemSpecialEffectHf>(file.NextLE<uint32_t>()); item._iDamAcFlags = static_cast<ItemSpecialEffectHf>(file.NextLE<uint32_t>());
@ -1147,11 +1155,11 @@ int getHellfireLevelType(int type)
void SaveItem(SaveHelper &file, const Item &item) void SaveItem(SaveHelper &file, const Item &item)
{ {
auto idx = item.IDidx; int32_t idx = item.IDidx != IDI_NONE ? AllItemsList[item.IDidx].iMappingId : -1;
if (!gbIsHellfire) if (!gbIsHellfire && idx < IDI_NUM_DEFAULT_ITEMS)
idx = RemapItemIdxToDiablo(idx); idx = RemapItemIdxToDiablo(static_cast<_item_indexes>(idx));
if (gbIsSpawn) if (gbIsSpawn && idx < IDI_NUM_DEFAULT_ITEMS)
idx = RemapItemIdxToSpawn(idx); idx = RemapItemIdxToSpawn(static_cast<_item_indexes>(idx));
ItemType iType = item._itype; ItemType iType = item._itype;
if (idx == -1) { if (idx == -1) {
idx = _item_indexes::IDI_GOLD; idx = _item_indexes::IDI_GOLD;

6
Source/lua/modules/items.cpp

@ -453,10 +453,10 @@ void RegisterItemSpecialEffectHfEnum(sol::state_view &lua)
}); });
} }
void AddItemDataFromTsv(const std::string_view path) void AddItemDataFromTsv(const std::string_view path, const int32_t baseMappingId)
{ {
DataFile dataFile = DataFile::loadOrDie(path); DataFile dataFile = DataFile::loadOrDie(path);
LoadItemDatFromFile(dataFile, path); LoadItemDatFromFile(dataFile, path, baseMappingId);
} }
void AddUniqueItemDataFromTsv(const std::string_view path, const int32_t baseMappingId) void AddUniqueItemDataFromTsv(const std::string_view path, const int32_t baseMappingId)
@ -482,7 +482,7 @@ sol::table LuaItemModule(sol::state_view &lua)
sol::table table = lua.create_table(); sol::table table = lua.create_table();
LuaSetDocFn(table, "addItemDataFromTsv", "(path: string)", AddItemDataFromTsv); LuaSetDocFn(table, "addItemDataFromTsv", "(path: string, baseMappingId: number)", AddItemDataFromTsv);
LuaSetDocFn(table, "addUniqueItemDataFromTsv", "(path: string, baseMappingId: number)", AddUniqueItemDataFromTsv); LuaSetDocFn(table, "addUniqueItemDataFromTsv", "(path: string, baseMappingId: number)", AddUniqueItemDataFromTsv);
return table; return table;

Loading…
Cancel
Save