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. */
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. */
ankerl::unordered_dense::map<std::string, int8_t> AdditionalUniqueBaseItemStringsToIndices;
@ -548,10 +551,11 @@ tl::expected<goodorevil, std::string> ParseAffixAlignment(std::string_view value
} // namespace
void LoadItemDatFromFile(DataFile &dataFile, std::string_view filename)
void LoadItemDatFromFile(DataFile &dataFile, std::string_view filename, int32_t baseMappingId)
{
dataFile.skipHeaderOrDie(filename);
int32_t currentMappingId = baseMappingId;
AllItemsList.reserve(AllItemsList.size() + dataFile.numRecords());
for (DataFileRecord record : dataFile) {
RecordReader reader { record, filename };
@ -579,6 +583,14 @@ void LoadItemDatFromFile(DataFile &dataFile, std::string_view filename)
reader.read("spell", item.iSpell, ParseSpellId);
reader.readBool("usable", item.iUsable);
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();
}
@ -592,7 +604,8 @@ void LoadItemDat()
AllItemsList.clear();
AdditionalUniqueBaseItemStringsToIndices.clear();
LoadItemDatFromFile(dataFile, filename);
ItemMappingIdsToIndices.clear();
LoadItemDatFromFile(dataFile, filename, 0);
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_ARENAPOT,
IDI_LAST = IDI_ARENAPOT,
IDI_NUM_DEFAULT_ITEMS,
IDI_NONE = -1,
};
@ -511,6 +511,7 @@ struct ItemData {
SpellID iSpell;
bool iUsable;
uint16_t iValue;
int32_t iMappingId;
};
enum item_effect_type : int8_t {
@ -647,12 +648,13 @@ struct UniqueItem {
};
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> ItemSuffixes;
extern DVL_API_FOR_TEST std::vector<UniqueItem> UniqueItems;
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 LoadItemData();

28
Source/loadsave.cpp

@ -352,13 +352,21 @@ struct LevelConversionData {
item._iMinDex = file.NextLE<int8_t>();
file.Skip(1); // Alignment
item._iStatFlag = file.NextBool32();
item.IDidx = static_cast<_item_indexes>(file.NextLE<int32_t>());
if (gbIsSpawn) {
item.IDidx = RemapItemIdxFromSpawn(item.IDidx);
int32_t itemMappingId = file.NextLE<int32_t>();
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) {
item.IDidx = RemapItemIdxFromDiablo(item.IDidx);
const auto findIt = ItemMappingIdsToIndices.find(itemMappingId);
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>();
if (gbIsHellfireSaveGame)
item._iDamAcFlags = static_cast<ItemSpecialEffectHf>(file.NextLE<uint32_t>());
@ -1147,11 +1155,11 @@ int getHellfireLevelType(int type)
void SaveItem(SaveHelper &file, const Item &item)
{
auto idx = item.IDidx;
if (!gbIsHellfire)
idx = RemapItemIdxToDiablo(idx);
if (gbIsSpawn)
idx = RemapItemIdxToSpawn(idx);
int32_t idx = item.IDidx != IDI_NONE ? AllItemsList[item.IDidx].iMappingId : -1;
if (!gbIsHellfire && idx < IDI_NUM_DEFAULT_ITEMS)
idx = RemapItemIdxToDiablo(static_cast<_item_indexes>(idx));
if (gbIsSpawn && idx < IDI_NUM_DEFAULT_ITEMS)
idx = RemapItemIdxToSpawn(static_cast<_item_indexes>(idx));
ItemType iType = item._itype;
if (idx == -1) {
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);
LoadItemDatFromFile(dataFile, path);
LoadItemDatFromFile(dataFile, path, 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();
LuaSetDocFn(table, "addItemDataFromTsv", "(path: string)", AddItemDataFromTsv);
LuaSetDocFn(table, "addItemDataFromTsv", "(path: string, baseMappingId: number)", AddItemDataFromTsv);
LuaSetDocFn(table, "addUniqueItemDataFromTsv", "(path: string, baseMappingId: number)", AddUniqueItemDataFromTsv);
return table;

Loading…
Cancel
Save