diff --git a/Memory.xml b/Memory.xml index 25df466d4..3e6b2e998 100644 --- a/Memory.xml +++ b/Memory.xml @@ -895,6 +895,7 @@ + @@ -3013,6 +3014,7 @@ + diff --git a/library/include/dfhack/modules/Creatures.h b/library/include/dfhack/modules/Creatures.h index 3d0520c40..f175aad3a 100644 --- a/library/include/dfhack/modules/Creatures.h +++ b/library/include/dfhack/modules/Creatures.h @@ -318,9 +318,13 @@ namespace DFHack const uint16_t x2, const uint16_t y2,const uint16_t z2); bool ReadCreature(const int32_t index, t_creature & furball); bool ReadJob(const t_creature * furball, std::vector & mat); + bool ReadInventoryIdx(const uint32_t index, std::vector & item); bool ReadInventoryPtr(const uint32_t index, std::vector & item); + bool ReadOwnedItemsIdx(const uint32_t index, std::vector & item); + bool ReadOwnedItemsPtr(const uint32_t index, std::vector & item); + int32_t FindIndexById(int32_t id); /* Getters */ diff --git a/library/include/dfhack/modules/Items.h b/library/include/dfhack/modules/Items.h index b164ff287..966bd1b99 100644 --- a/library/include/dfhack/modules/Items.h +++ b/library/include/dfhack/modules/Items.h @@ -116,6 +116,10 @@ public: ~Items(); bool Start(); bool Finish(); + + bool readItemVector(std::vector &items); + uint32_t findItemByID(int32_t id); + /// get a string describing an item std::string getItemDescription(const dfh_item & item, Materials * Materials); /// get a short name for an item diff --git a/library/modules/Creatures.cpp b/library/modules/Creatures.cpp index 4aa12063d..d2eb757e3 100644 --- a/library/modules/Creatures.cpp +++ b/library/modules/Creatures.cpp @@ -56,6 +56,7 @@ struct Creatures::Private bool Ft_job_materials; bool Ft_soul; bool Ft_inventory; + bool Ft_owned_items; struct t_offsets { // creature offsets @@ -93,6 +94,7 @@ struct Creatures::Private uint32_t birth_year_offset; uint32_t birth_time_offset; uint32_t inventory_offset; + uint32_t owned_items_offset; // creature job stuff int32_t job_type_offset; int32_t job_id_offset; @@ -137,7 +139,7 @@ Creatures::Creatures(DFContextShared* _d) OffsetGroup * OG_name = minfo->getGroup("name"); OffsetGroup * OG_jobs = OG_Creatures->getGroup("job"); OffsetGroup * OG_job_mats = OG_jobs->getGroup("material"); - d->Ft_basic = d->Ft_advanced = d->Ft_jobs = d->Ft_soul = d->Ft_inventory = d->Ft_job_materials = false; + d->Ft_basic = d->Ft_advanced = d->Ft_jobs = d->Ft_soul = d->Ft_inventory = d->Ft_owned_items = d->Ft_job_materials = false; Private::t_offsets &creatures = d->creatures; try @@ -187,6 +189,12 @@ Creatures::Creatures(DFContextShared* _d) } catch(Error::All&){}; try + { + creatures.owned_items_offset = OG_creature_ex->getOffset("owned_items_vector"); + d->Ft_owned_items = true; + } + catch(Error::All&){}; + try { creatures.soul_vector_offset = OG_creature_ex->getOffset("soul_vector"); creatures.default_soul_offset = OG_creature_ex->getOffset("current_soul"); @@ -692,6 +700,28 @@ bool Creatures::ReadInventoryPtr(const uint32_t temp, std::vector & it return true; } +bool Creatures::ReadOwnedItemsIdx(const uint32_t index, std::vector & item) +{ + if(!d->Started || !d->Ft_owned_items) return false; + uint32_t temp = d->p_cre->at (index); + return this->ReadOwnedItemsPtr(temp, item); +} + +bool Creatures::ReadOwnedItemsPtr(const uint32_t temp, std::vector & item) +{ + unsigned int i; + if(!d->Started || !d->Ft_owned_items) return false; + Process * p = d->owner; + + DfVector citem(p, temp + d->creatures.owned_items_offset); + if(citem.size() == 0) + return false; + item.resize(citem.size()); + for(i=0;icreatures; diff --git a/library/modules/Items.cpp b/library/modules/Items.cpp index 238352c08..033a2b929 100644 --- a/library/modules/Items.cpp +++ b/library/modules/Items.cpp @@ -421,9 +421,11 @@ class Items::Private Process * owner; std::map descType; std::map descVTable; + std::map idLookupTable; uint32_t refVectorOffset; uint32_t refIDOffset; uint32_t idFieldOffset; + uint32_t itemVectorAddress; ClassNameCheck isOwnerRefClass; }; @@ -434,10 +436,15 @@ Items::Items(DFContextShared * d_) d->owner = d_->p; d->refVectorOffset = d->refIDOffset = 0; d->isOwnerRefClass = ClassNameCheck("general_ref_unit_itemownerst"); + + DFHack::OffsetGroup* itemGroup = d_->offset_descriptor->getGroup("Items"); + d->itemVectorAddress = itemGroup->getAddress("items_vector"); + d->idFieldOffset = itemGroup->getOffset("id"); } bool Items::Start() { + d->idLookupTable.clear(); return true; } @@ -446,6 +453,35 @@ bool Items::Finish() return true; } +bool Items::readItemVector(std::vector &items) +{ + DFHack::DfVector p_items(d->owner, d->itemVectorAddress); + + d->idLookupTable.clear(); + items.resize(p_items.size()); + + for (unsigned i = 0; i < p_items.size(); i++) { + uint32_t ptr = p_items[i]; + items[i] = ptr; + d->idLookupTable[d->owner->readDWord(ptr + d->idFieldOffset)] = ptr; + } + + return true; +} + +uint32_t Items::findItemByID(int32_t id) +{ + if (id < 0) + return 0; + + if (d->idLookupTable.empty()) { + std::vector tmp; + readItemVector(tmp); + } + + return d->idLookupTable[id]; +} + Items::~Items() { Finish(); diff --git a/tools/examples/creaturedump.cpp b/tools/examples/creaturedump.cpp index ad8ac7c8a..32beae150 100644 --- a/tools/examples/creaturedump.cpp +++ b/tools/examples/creaturedump.cpp @@ -285,19 +285,34 @@ void printCreature(DFHack::Context * DF, const DFHack::t_creature & creature) } } - //std::vector inventory; // FIXME: TOO BAD... - /* - if( Creatures->ReadInventoryPtr(creature.origin, inventory) ) + std::vector inventory; + if( Creatures->ReadInventoryPtr(creature.origin, inventory)) { DFHack::Items * Items = DF->getItems(); printf("\tInventory:\n"); for(unsigned int i = 0; i < inventory.size(); i++) { - printf("\t\t%s\n", Items->getItemDescription(inventory[i], Materials).c_str()); + DFHack::dfh_item item; + if (Items->readItem(inventory[i], item)) + printf("\t\t%d: %s\n", item.id, Items->getItemDescription(item, Materials).c_str()); + } + } + + std::vector owned; + if( Creatures->ReadOwnedItemsPtr(creature.origin, owned)) + { + DFHack::Items * Items = DF->getItems(); + printf("\tOwns:\n"); + for (int i = 0; i < owned.size(); i++) { + uint32_t pitem = Items->findItemByID(owned[i]); + DFHack::dfh_item item; + if (!pitem || !Items->readItem(pitem,item)) + pitem = 0; + printf("\t\t%d: %s\n", owned[i], + pitem ? Items->getItemDescription(item, Materials).c_str() : "?"); } } - */ /* if(creature.pregnancy_timer > 0)