Creatures module rewrite

develop
Petr Mrázek 2011-09-18 13:49:10 +02:00
parent d47e9b35a0
commit dca4c43b0b
8 changed files with 616 additions and 341 deletions

@ -260,6 +260,7 @@ namespace DFHack
/**
* \ingroup grp_creatures
*/
/*
struct t_like
{
int16_t type;
@ -268,25 +269,23 @@ namespace DFHack
t_matglossPair material;
bool active;
};
*/
// FIXME: THIS IS VERY, VERY BAD.
#define NUM_CREATURE_LABORS 96
#define NUM_CREATURE_TRAITS 30
#define NUM_CREATURE_LABORS 102
#define NUM_CREATURE_MENTAL_ATTRIBUTES 13
#define NUM_CREATURE_PHYSICAL_ATTRIBUTES 6
/**
* structure for holding a DF creature's soul
* structure for holding a copy of a creature's soul
* \ingroup grp_creatures
*/
struct t_soul
{
uint8_t numSkills;
t_skill skills[256];
/*
uint8_t numLikes;
t_like likes[32];
*/
//uint8_t numLikes;
//t_like likes[32];
uint16_t traits[NUM_CREATURE_TRAITS];
t_attrib analytical_ability;
t_attrib focus;
@ -302,15 +301,15 @@ namespace DFHack
t_attrib empathy;
t_attrib social_awareness;
};
#define MAX_COLORS 15
struct df_creature;
/**
* structure for holding a DF creature
* structure for holding a copy of a creature
* \ingroup grp_creatures
*/
struct t_creature
{
uint32_t origin;
df_creature * origin;
uint16_t x;
uint16_t y;
uint16_t z;
@ -328,7 +327,7 @@ namespace DFHack
t_name artifact_name;
uint8_t profession;
char custom_profession[128];
std::string custom_profession;
// enabled labors
uint8_t labors[NUM_CREATURE_LABORS];
@ -346,8 +345,8 @@ namespace DFHack
uint8_t sex;
uint16_t caste;
uint32_t pregnancy_timer; //Countdown timer to giving birth
bool has_default_soul;
t_soul defaultSoul;
//bool has_default_soul;
//t_soul defaultSoul;
uint32_t nbcolors;
uint32_t color[MAX_COLORS];
@ -355,7 +354,375 @@ namespace DFHack
uint32_t birth_time;
};
class DFContextShared;
/**
* Creature attribute descriptor
* \ingroup grp_creatures
*/
struct df_attrib
{
uint32_t unk_0;
uint32_t unk_4;
uint32_t unk_8;
uint32_t unk_c;
uint32_t unk_10;
uint32_t unk_14;
uint32_t unk_18;
};
/**
* Creature skil descriptor
* \ingroup grp_creatures
*/
struct df_skill
{
uint16_t id; // 0
int32_t rating; // 4
uint32_t experience; // 8
uint32_t unk_c;
uint32_t rusty; // 10
uint32_t unk_14;
uint32_t unk_18;
uint32_t unk_1c;
};
/**
* A creature's soul, as it appears in DF memory
* \ingroup grp_creatures
*/
struct df_soul
{
uint32_t unk_0;
df_name name; // 4
uint32_t unk_70;
uint16_t unk_74;
uint16_t unk_76;
int32_t unk_78;
int32_t unk_7c;
int32_t unk_80;
int32_t unk_84;
df_attrib mental[NUM_CREATURE_MENTAL_ATTRIBUTES]; // 88..1f3
std::vector<df_skill*> skills; // 1f4;
std::vector<void*> unk_204; // pointers to 14 0x14-byte structures ... likes?
uint16_t traits[NUM_CREATURE_TRAITS]; // 214
std::vector<int16_t*> unk_250; // 1 pointer to 2 shorts
uint32_t unk_260;
uint32_t unk_264;
uint32_t unk_268;
uint32_t unk_26c;
};
/**
* A creature job - what it's supposed to be doing.
* \ingroup grp_creatures
*/
struct df_job
{
};
/**
* A creature, as it appears in DF memory
* \ingroup grp_creatures
*/
struct df_creature
{
df_name name; // 0
std::string custom_profession; // 6c (MSVC)
uint8_t profession; // 88
uint32_t race; // 8c
uint16_t x; // 90
uint16_t y; // 92
uint16_t z; // 94
uint16_t unk_x96; // 96
uint16_t unk_y98; // 98
uint16_t unk_z9a; // 9a
uint32_t unk_9c;
uint16_t unk_a0;
int16_t unk_a2;
uint32_t unk_a4;
uint16_t dest_x; // a8
uint16_t dest_y; // aa
uint16_t dest_z; // ac
uint16_t unk_ae; // -1
std::vector<uint32_t> unk_b0; // b0->df (3*4 in MSVC) -> 68->8b (3*3 in glibc)
std::vector<uint32_t> unk_c0;
std::vector<uint32_t> unk_d0;
t_creaturflags1 flags1; // e0
t_creaturflags2 flags2; // e4
t_creaturflags3 flags3; // e8
void ** unk_ec;
int32_t unk_f0;
int16_t unk_f4;
int16_t unk_f6;
uint16_t caste; // f8
uint8_t sex; // fa
uint32_t id; // fc
uint16_t unk_100;
uint16_t unk_102;
int32_t unk_104;
uint32_t civ; // 108
uint32_t unk_10c;
int32_t unk_110;
std::vector<uint32_t> unk_114;
std::vector<uint32_t> unk_124;
std::vector<uint32_t> unk_134;
uint32_t unk_144;
std::vector<void*> unk_148;
std::vector<void*> unk_158;
int32_t unk_168;
int32_t unk_16c;
uint32_t unk_170;
uint32_t unk_174;
uint16_t unk_178;
std::vector<uint32_t> unk_17c;
std::vector<uint32_t> unk_18c;
std::vector<uint32_t> unk_19c;
std::vector<uint32_t> unk_1ac;
uint32_t pickup_equipment_bit; // 1bc
std::vector<uint32_t> unk_1c0;
std::vector<uint32_t> unk_1d0;
std::vector<uint32_t> unk_1e0;
int32_t unk_1f0;
int16_t unk_1f4;
int32_t unk_1f8;
int32_t unk_1fc;
int32_t unk_200;
int16_t unk_204;
uint32_t unk_208;
uint32_t unk_20c;
int16_t mood; // 210
uint32_t pregnancy_timer; // 214
void* pregnancy_ptr; // 218
int32_t unk_21c;
uint32_t unk_220;
uint32_t birth_year; // 224
uint32_t birth_time; // 228
uint32_t unk_22c;
uint32_t unk_230;
uint32_t unk_234;
uint32_t unk_238;
int32_t unk_23c;
int32_t unk_240;
int32_t unk_244;
int32_t unk_248;
int32_t unk_24c;
int32_t unk_250;
int32_t unk_254;
int32_t unk_258;
int32_t unk_25c;
int32_t unk_260;
int16_t unk_264;
int32_t unk_268;
int32_t unk_26c;
int16_t unk_270;
int32_t unk_274;
int32_t unk_278;
int32_t unk_27c;
int16_t unk_280;
int32_t unk_284;
std::vector<t_item *> inventory; // 288 - vector of item pointers
std::vector<int32_t> owned_items; // 298 - vector of item IDs
std::vector<uint32_t> unk_2a8;
std::vector<uint32_t> unk_2b8;
std::vector<uint32_t> unk_2c8;
uint32_t unk_2d8;
uint32_t unk_2dc;
uint32_t unk_2e0;
uint32_t unk_2e4;
uint32_t unk_2e8;
uint32_t unk_2ec;
uint32_t unk_2f0;
df_job * current_job; // 2f4
uint32_t unk_2f8; // possibly current skill?
uint32_t unk_2fc;
uint32_t unk_300;
uint32_t unk_304;
std::vector<uint32_t> unk_308;
std::vector<uint32_t> unk_318;
std::vector<uint32_t> unk_328;
std::vector<uint32_t> unk_338;
std::vector<uint32_t> unk_348;
std::vector<uint32_t> unk_358;
std::vector<uint32_t> unk_368;
std::vector<uint32_t> unk_378;
std::vector<uint32_t> unk_388;
uint32_t unk_398;
int32_t unk_39c;
int32_t unk_3a0;
int32_t unk_3a4;
int32_t unk_3a8;
int32_t unk_3ac;
int32_t unk_3b0;
int32_t unk_3b4;
int32_t unk_3b8;
int32_t unk_3bc;
int32_t unk_3c0;
uint32_t unk_3c4;
uint32_t unk_3c8;
df_attrib physical[NUM_CREATURE_PHYSICAL_ATTRIBUTES]; // 3cc..473
uint32_t unk_474;
uint32_t unk_478;
uint32_t unk_47c;
uint32_t unk_480;
uint32_t unk_484;
uint32_t unk_488;
uint32_t unk_48c; // blood_max?
uint32_t blood_count; // 490
uint32_t unk_494;
std::vector<void*> unk_498;
std::vector<uint16_t> unk_4a8;
std::vector<uint16_t> unk_4b8;
uint32_t unk_4c8;
std::vector<int16_t> unk_4cc;
std::vector<int32_t> unk_4dc;
std::vector<int32_t> unk_4ec;
std::vector<int32_t> unk_4fc;
std::vector<uint16_t> unk_50c;
void* unk_51c;
uint16_t unk_520;
uint16_t unk_522;
uint16_t* unk_524;
uint16_t unk_528;
uint16_t unk_52a;
std::vector<uint32_t> appearance; // 52c
int16_t unk_53c;
int16_t unk_53e;
int16_t unk_540;
int16_t unk_542;
int16_t unk_544;
int16_t unk_546;
int16_t unk_548;
int16_t unk_54a;
int16_t unk_54c;
int16_t unk_54e;
int16_t unk_550;
int16_t unk_552;
int16_t unk_x554; // coords ? (-30.000x3)
int16_t unk_y556;
int16_t unk_z558;
int16_t unk_x55a; // coords again
int16_t unk_y55c;
int16_t unk_z55e;
int16_t unk_560;
int16_t unk_562;
uint32_t unk_564;
uint32_t unk_568;
uint32_t unk_56c;
uint32_t unk_570;
uint32_t unk_574;
uint32_t unk_578;
uint32_t unk_57c;
uint32_t unk_580;
uint32_t unk_584;
uint32_t unk_588;
uint32_t unk_58c;
uint32_t unk_590;
uint32_t unk_594;
uint32_t unk_598;
uint32_t unk_59c;
std::vector<void*> unk_5a0;
void* unk_5b0; // pointer to X (12?) vector<int16_t>
uint32_t unk_5b4; // 0x3e8 (1000)
uint32_t unk_5b8; // 0x3e8 (1000)
std::vector<uint32_t> unk_5bc;
std::vector<uint32_t> unk_5cc;
int16_t unk_5dc;
int16_t unk_5de;
df_name artifact_name; // 5e0
std::vector<df_soul*> souls; // 64c
df_soul* current_soul; // 65c
std::vector<uint32_t> unk_660;
uint8_t labors[NUM_CREATURE_LABORS]; // 670..6cf
std::vector<uint32_t> unk_6d0;
std::vector<uint32_t> unk_6e0;
std::vector<uint32_t> unk_6f0;
std::vector<uint32_t> unk_700;
uint32_t happiness; // 710
uint16_t unk_714;
uint16_t unk_716;
std::vector<void*> unk_718;
std::vector<void*> unk_728;
std::vector<void*> unk_738;
std::vector<void*> unk_748;
uint16_t unk_758;
uint16_t unk_x75a; // coords (-30000*3)
uint16_t unk_y75c;
uint16_t unk_z75e;
std::vector<uint16_t> unk_760;
std::vector<uint16_t> unk_770;
std::vector<uint16_t> unk_780;
uint32_t hist_figure_id; // 790
uint16_t able_stand; // 794
uint16_t able_stand_impair; // 796
uint16_t able_grasp; // 798
uint16_t able_grasp_impair; // 79a
uint32_t unk_79c;
uint32_t unk_7a0;
std::vector<void*> unk_7a4;
uint32_t unk_7b4;
uint32_t unk_7b8;
uint32_t unk_7bc;
int32_t unk_7c0;
std::vector<uint32_t> unk_7c4;
std::vector<uint32_t> unk_7d4;
std::vector<uint32_t> unk_7e4;
std::vector<uint32_t> unk_7f4;
std::vector<uint32_t> unk_804;
std::vector<uint32_t> unk_814;
uint32_t unk_824;
void* unk_828;
void* unk_82c;
uint32_t unk_830;
void* unk_834;
void* unk_838;
void* unk_83c;
std::vector<void*> unk_840;
std::vector<uint32_t> unk_850;
std::vector<uint32_t> unk_860;
uint32_t unk_870;
uint32_t unk_874;
std::vector<uint8_t> unk_878;
std::vector<uint8_t> unk_888;
std::vector<uint32_t> unk_898;
std::vector<uint8_t> unk_8a8;
std::vector<uint16_t> unk_8b8;
std::vector<uint16_t> unk_8c8;
std::vector<uint32_t> unk_8d8;
std::vector<uint32_t> unk_8e8;
std::vector<uint32_t> unk_8f8;
std::vector<uint32_t> unk_908;
int32_t unk_918;
uint16_t unk_91c;
uint16_t unk_91e;
uint16_t unk_920;
uint16_t unk_922;
uint32_t unk_924;
uint32_t unk_928;
std::vector<uint16_t> unk_92c;
uint32_t unk_93c;
};
/**
* The Creatures module - allows reading all non-vermin creatures and their properties
* \ingroup grp_modules
@ -363,6 +730,8 @@ namespace DFHack
*/
class DFHACK_EXPORT Creatures : public Module
{
public:
std::vector <df_creature *> * creatures;
public:
Creatures();
~Creatures();
@ -372,17 +741,19 @@ namespace DFHack
/* Read Functions */
// Read creatures in a box, starting with index. Returns -1 if no more creatures
// found. Call repeatedly do get all creatures in a specified box (uses tile coords)
int32_t ReadCreatureInBox(const int32_t index, t_creature & furball,
int32_t GetCreatureInBox(const int32_t index, df_creature ** furball,
const uint16_t x1, const uint16_t y1,const uint16_t z1,
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<t_material> & mat);
df_creature * GetCreature(const int32_t index);
void CopyCreature(df_creature * source, t_creature & target);
bool ReadJob(const df_creature * unit, std::vector<t_material> & mat);
bool ReadInventoryIdx(const uint32_t index, std::vector<uint32_t> & item);
bool ReadInventoryPtr(const uint32_t index, std::vector<uint32_t> & item);
bool ReadInventoryByIdx(const uint32_t index, std::vector<t_item *> & item);
bool ReadInventoryByPtr(const df_creature * unit, std::vector<t_item *> & item);
bool ReadOwnedItemsIdx(const uint32_t index, std::vector<int32_t> & item);
bool ReadOwnedItemsPtr(const uint32_t index, std::vector<int32_t> & item);
bool ReadOwnedItemsByIdx(const uint32_t index, std::vector<int32_t> & item);
bool ReadOwnedItemsByPtr(const df_creature * unit, std::vector<int32_t> & item);
int32_t FindIndexById(int32_t id);
@ -391,27 +762,27 @@ namespace DFHack
int32_t GetDwarfCivId ( void );
/* Write Functions */
bool WriteLabors(const uint32_t index, uint8_t labors[NUM_CREATURE_LABORS]);
bool WriteHappiness(const uint32_t index, const uint32_t happinessValue);
bool WriteFlags(const uint32_t index, const uint32_t flags1, const uint32_t flags2);
bool WriteFlags(const uint32_t index, const uint32_t flags1, const uint32_t flags2, uint32_t flags3);
bool WriteSkills(const uint32_t index, const t_soul &soul);
bool WriteAttributes(const uint32_t index, const t_creature &creature);
bool WriteSex(const uint32_t index, const uint8_t sex);
bool WriteTraits(const uint32_t index, const t_soul &soul);
bool WriteMood(const uint32_t index, const uint16_t mood);
bool WriteMoodSkill(const uint32_t index, const uint16_t moodSkill);
bool WriteJob(const t_creature * furball, std::vector<t_material> const& mat);
bool WritePos(const uint32_t index, const t_creature &creature);
bool WriteCiv(const uint32_t index, const int32_t civ);
bool WritePregnancy(const uint32_t index, const uint32_t pregTimer);
void CopyNameTo(t_creature &creature, uint32_t address);
//bool WriteLabors(const uint32_t index, uint8_t labors[NUM_CREATURE_LABORS]);
//bool WriteHappiness(const uint32_t index, const uint32_t happinessValue);
//bool WriteFlags(const uint32_t index, const uint32_t flags1, const uint32_t flags2);
//bool WriteFlags(const uint32_t index, const uint32_t flags1, const uint32_t flags2, uint32_t flags3);
//bool WriteSkills(const uint32_t index, const t_soul &soul);
//bool WriteAttributes(const uint32_t index, const t_creature &creature);
//bool WriteSex(const uint32_t index, const uint8_t sex);
//bool WriteTraits(const uint32_t index, const t_soul &soul);
//bool WriteMood(const uint32_t index, const uint16_t mood);
//bool WriteMoodSkill(const uint32_t index, const uint16_t moodSkill);
//bool WriteJob(const t_creature * furball, std::vector<t_material> const& mat);
//bool WritePos(const uint32_t index, const t_creature &creature);
//bool WriteCiv(const uint32_t index, const int32_t civ);
//bool WritePregnancy(const uint32_t index, const uint32_t pregTimer);
void CopyNameTo(df_creature *creature, df_name * target);
protected:
friend class Items;
bool RemoveOwnedItemIdx(const uint32_t index, int32_t id);
bool RemoveOwnedItemPtr(const uint32_t index, int32_t id);
bool RemoveOwnedItemByIdx(const uint32_t index, int32_t id);
bool RemoveOwnedItemByPtr(df_creature * unit, int32_t id);
private:
struct Private;

@ -67,10 +67,10 @@ namespace DFHack
// names, used by a few other modules.
bool InitReadNames();
bool readName(t_name & name, uint32_t address);
bool copyName(uint32_t address, uint32_t target);
bool readName(t_name & name, df_name * address);
bool copyName(df_name * address, df_name * target);
// translate a name using the loaded dictionaries
std::string TranslateName(const DFHack::t_name& name, bool inEnglish = true);
std::string TranslateName(const DFHack::df_name * name, bool inEnglish = true);
private:
struct Private;

@ -30,6 +30,7 @@ distribution.
#include <vector>
#include <map>
#include <cstring>
#include <algorithm>
using namespace std;
@ -52,6 +53,7 @@ struct Creatures::Private
{
bool Inited;
bool Started;
/*
bool Ft_basic;
bool Ft_advanced;
bool Ft_jobs;
@ -111,12 +113,13 @@ struct Creatures::Private
int32_t job_material_flags_o;
// creature job material stuff
} creatures;
*/
uint32_t creature_module;
uint32_t dwarf_race_index_addr;
uint32_t dwarf_civ_id_addr;
bool IdMapReady;
std::map<int32_t, int32_t> IdMap;
DfVector <uint32_t> *p_cre;
//DfVector <uint32_t> *p_cre;
Process *owner;
Translation * trans;
};
@ -129,13 +132,13 @@ Module* DFHack::createCreatures()
Creatures::Creatures()
{
Core & c = Core::getInstance();
creatures = 0;
d = new Private;
d->owner = c.p;
VersionInfo * minfo = c.vinfo;
d->Inited = false;
d->Started = false;
d->IdMapReady = false;
d->p_cre = NULL;
d->trans = c.getTranslation();
d->trans->InitReadNames(); // throws on error
@ -146,90 +149,12 @@ Creatures::Creatures()
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_owned_items = d->Ft_job_materials = false;
Private::t_offsets &creatures = d->creatures;
try
{
// Creatures
creatures.vector = OG_Creatures->getAddress ("vector");
creatures = (vector <df_creature *> *) OG_Creatures->getAddress ("vector");
d->dwarf_race_index_addr = OG_Creatures->getAddress("current_race");
d->dwarf_civ_id_addr = OG_Creatures->getAddress("current_civ");
// Creatures/creature
creatures.name_offset = OG_creature->getOffset ("name");
creatures.custom_profession_offset = OG_creature->getOffset ("custom_profession");
creatures.profession_offset = OG_creature->getOffset ("profession");
creatures.race_offset = OG_creature->getOffset ("race");
creatures.pos_offset = OG_creature->getOffset ("position");
creatures.flags1_offset = OG_creature->getOffset ("flags1");
creatures.flags2_offset = OG_creature->getOffset ("flags2");
creatures.flags3_offset = OG_creature->getOffset ("flags3");
creatures.sex_offset = OG_creature->getOffset ("sex");
creatures.caste_offset = OG_creature->getOffset ("caste");
creatures.id_offset = OG_creature->getOffset ("id");
creatures.civ_offset = OG_creature->getOffset ("civ");
// name struct
creatures.name_firstname_offset = OG_name->getOffset("first");
creatures.name_nickname_offset = OG_name->getOffset("nick");
creatures.name_words_offset = OG_name->getOffset("second_words");
d->Ft_basic = true;
try
{
creatures.pickup_equipment_bit = OG_creature_ex->getOffset("pickup_equipment_bit");
creatures.mood_offset = OG_creature_ex->getOffset("mood");
creatures.pregnancy_offset = OG_creature_ex->getOffset("pregnancy");
creatures.pregnancy_ptr_offset = OG_creature_ex->getOffset("pregnancy_ptr");
creatures.birth_year_offset = OG_creature_ex->getOffset("birth_year");
creatures.birth_time_offset = OG_creature_ex->getOffset("birth_time");
creatures.current_job_offset = OG_creature_ex->getOffset("current_job");
creatures.mood_skill_offset = OG_creature_ex->getOffset("current_job_skill");
creatures.physical_offset = OG_creature_ex->getOffset("physical");
creatures.appearance_vector_offset = OG_creature_ex->getOffset("appearance_vector");
creatures.artifact_name_offset = OG_creature_ex->getOffset("artifact_name");
creatures.labors_offset = OG_creature_ex->getOffset ("labors");
creatures.happiness_offset = OG_creature_ex->getOffset ("happiness");
d->Ft_advanced = true;
}catch(Error::All&){};
try
{
creatures.inventory_offset = OG_creature_ex->getOffset("inventory_vector");
d->Ft_inventory = true;
}
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");
creatures.soul_mental_offset = OG_soul->getOffset("mental");
creatures.soul_skills_vector_offset = OG_soul->getOffset("skills_vector");
creatures.soul_traits_offset = OG_soul->getOffset("traits");
d->Ft_soul = true;
}
catch(Error::All&){};
try
{
creatures.job_type_offset = OG_jobs->getOffset("type");
creatures.job_id_offset = OG_jobs->getOffset("id");
d->Ft_jobs = true;
try
{
creatures.job_materials_vector = OG_jobs->getOffset("materials_vector");
creatures.job_material_itemtype_o = OG_job_mats->getOffset("maintype");
creatures.job_material_subtype_o = OG_job_mats->getOffset("sectype1");
creatures.job_material_subindex_o = OG_job_mats->getOffset("sectype2");
creatures.job_material_index_o = OG_job_mats->getOffset("sectype3");
creatures.job_material_flags_o = OG_job_mats->getOffset("flags");
d->Ft_job_materials = true;
}
catch(Error::All&){};
}
catch(Error::All&){};
}
catch(Error::All&){};
d->Inited = true;
@ -243,11 +168,10 @@ Creatures::~Creatures()
bool Creatures::Start( uint32_t &numcreatures )
{
if(d->Ft_basic)
if(creatures)
{
d->p_cre = new DfVector <uint32_t> (d->creatures.vector);
d->Started = true;
numcreatures = d->p_cre->size();
numcreatures = creatures->size();
d->IdMapReady = false;
return true;
}
@ -256,96 +180,116 @@ bool Creatures::Start( uint32_t &numcreatures )
bool Creatures::Finish()
{
if(d->p_cre)
{
delete d->p_cre;
d->p_cre = 0;
}
d->Started = false;
return true;
}
bool Creatures::ReadCreature (const int32_t index, t_creature & furball)
df_creature * Creatures::GetCreature (const int32_t index)
{
if(!d->Started) return false;
memset(&furball, 0, sizeof(t_creature));
// SHM fast path
Process * p = d->owner;
if(!d->Started) return nullptr;
// read pointer from vector at position
uint32_t addr_cr = d->p_cre->at (index);
furball.origin = addr_cr;
Private::t_offsets &offs = d->creatures;
if(index > creatures->size())
return nullptr;
return creatures->at(index);
}
//read creature from memory
if(d->Ft_basic)
{
// name
d->trans->readName(furball.name,addr_cr + offs.name_offset);
// basic stuff
p->readDWord (addr_cr + offs.id_offset, furball.id);
p->read (addr_cr + offs.pos_offset, 3 * sizeof (uint16_t), (uint8_t *) & (furball.x)); // xyz really
p->readDWord (addr_cr + offs.race_offset, furball.race);
furball.civ = p->readDWord (addr_cr + offs.civ_offset);
p->readByte (addr_cr + offs.sex_offset, furball.sex);
p->readWord (addr_cr + offs.caste_offset, furball.caste);
p->readDWord (addr_cr + offs.flags1_offset, furball.flags1.whole);
p->readDWord (addr_cr + offs.flags2_offset, furball.flags2.whole);
p->readDWord (addr_cr + offs.flags3_offset, furball.flags3.whole);
// custom profession
p->readSTLString(addr_cr + offs.custom_profession_offset, furball.custom_profession, sizeof(furball.custom_profession));
// profession
furball.profession = p->readByte (addr_cr + offs.profession_offset);
}
if(d->Ft_advanced)
// returns index of creature actually read or -1 if no creature can be found
int32_t Creatures::GetCreatureInBox (int32_t index, df_creature ** furball,
const uint16_t x1, const uint16_t y1, const uint16_t z1,
const uint16_t x2, const uint16_t y2, const uint16_t z2)
{
if (!d->Started)
return -1;
Process *p = d->owner;
uint16_t coords[3];
uint32_t size = creatures->size();
while (uint32_t(index) < size)
{
// happiness
p->readDWord (addr_cr + offs.happiness_offset, furball.happiness);
// physical attributes
p->read(addr_cr + offs.physical_offset,
sizeof(t_attrib) * NUM_CREATURE_PHYSICAL_ATTRIBUTES,
(uint8_t *)&furball.strength);
// mood stuff
furball.mood = (int16_t) p->readWord (addr_cr + offs.mood_offset);
furball.mood_skill = p->readWord (addr_cr + offs.mood_skill_offset);
d->trans->readName(furball.artifact_name, addr_cr + offs.artifact_name_offset);
// labors
p->read (addr_cr + offs.labors_offset, NUM_CREATURE_LABORS, furball.labors);
furball.birth_year = p->readDWord (addr_cr + offs.birth_year_offset );
furball.birth_time = p->readDWord (addr_cr + offs.birth_time_offset );
furball.pregnancy_timer = p->readDWord (addr_cr + offs.pregnancy_offset );
// appearance
DfVector <uint32_t> app(addr_cr + offs.appearance_vector_offset);
furball.nbcolors = app.size();
if(furball.nbcolors>MAX_COLORS)
furball.nbcolors = MAX_COLORS;
for(uint32_t i = 0; i < furball.nbcolors; i++)
// read pointer from vector at position
df_creature * temp = creatures->at(index);
if (temp->x >= x1 && temp->x < x2)
{
furball.color[i] = app[i];
if (temp->y >= y1 && temp->y < y2)
{
if (temp->z >= z1 && temp->z < z2)
{
*furball = temp;
return index;
}
}
}
index++;
}
*furball = nullptr;
return -1;
}
//likes
/*
DfVector <uint32_t> likes(d->p, temp + offs.creature_likes_offset);
furball.numLikes = likes.getSize();
for(uint32_t i = 0;i<furball.numLikes;i++)
{
uint32_t temp2 = *(uint32_t *) likes[i];
p->read(temp2,sizeof(t_like),(uint8_t *) &furball.likes[i]);
}*/
void Creatures::CopyCreature(df_creature * source, t_creature & furball)
{
if(!d->Started) return;
// read pointer from vector at position
furball.origin = source;
//read creature from memory
// name
d->trans->readName(furball.name,&source->name);
// basic stuff
furball.id = source->id;
furball.x = source->x;
furball.y = source->y;
furball.z = source->z;
furball.race = source->race;
furball.civ = source->civ;
furball.sex = source->sex;
furball.caste = source->caste;
furball.flags1.whole = source->flags1.whole;
furball.flags2.whole = source->flags2.whole;
furball.flags3.whole = source->flags3.whole;
// custom profession
furball.custom_profession = source->custom_profession;
// profession
furball.profession = source->profession;
// happiness
furball.happiness = source->happiness;
// physical attributes
memcpy(&furball.strength, source->physical, sizeof(source->physical));
// mood stuff
furball.mood = source->mood;
furball.mood_skill = source->unk_2f8; // FIXME: really? More like currently used skill anyway.
d->trans->readName(furball.artifact_name, &source->artifact_name);
// labors
memcpy(&furball.labors, &source->labors, sizeof(furball.labors));
furball.birth_year = source->birth_year;
furball.birth_time = source->birth_time;
furball.pregnancy_timer = source->pregnancy_timer;
// appearance
furball.nbcolors = source->appearance.size();
if(furball.nbcolors>MAX_COLORS)
furball.nbcolors = MAX_COLORS;
for(uint32_t i = 0; i < furball.nbcolors; i++)
{
furball.color[i] = source->appearance[i];
}
//likes. FIXME: where do they fit in now? The soul?
/*
DfVector <uint32_t> likes(d->p, temp + offs.creature_likes_offset);
furball.numLikes = likes.getSize();
for(uint32_t i = 0;i<furball.numLikes;i++)
{
uint32_t temp2 = *(uint32_t *) likes[i];
p->read(temp2,sizeof(t_like),(uint8_t *) &furball.likes[i]);
}
*/
/*
if(d->Ft_soul)
{
/*
// enum soul pointer vector
DfVector <uint32_t> souls(p,temp + offs.creature_soul_vector_offset);
*/
uint32_t soul = p->readDWord(addr_cr + offs.default_soul_offset);
furball.has_default_soul = false;
@ -378,76 +322,39 @@ bool Creatures::ReadCreature (const int32_t index, t_creature & furball)
(uint8_t *) &furball.defaultSoul.traits);
}
}
if(d->Ft_jobs)
*/
/*
furball.current_job.occupationPtr = p->readDWord (addr_cr + offs.current_job_offset);
if(furball.current_job.occupationPtr)
{
furball.current_job.occupationPtr = p->readDWord (addr_cr + offs.current_job_offset);
if(furball.current_job.occupationPtr)
{
furball.current_job.active = true;
furball.current_job.jobType = p->readByte (furball.current_job.occupationPtr + offs.job_type_offset );
furball.current_job.jobId = p->readWord (furball.current_job.occupationPtr + offs.job_id_offset);
}
else
{
furball.current_job.active = false;
}
furball.current_job.active = true;
furball.current_job.jobType = p->readByte (furball.current_job.occupationPtr + offs.job_type_offset );
furball.current_job.jobId = p->readWord (furball.current_job.occupationPtr + offs.job_id_offset);
}
else
{
furball.current_job.active = false;
}
return true;
}
// returns index of creature actually read or -1 if no creature can be found
int32_t Creatures::ReadCreatureInBox (int32_t index, t_creature & furball,
const uint16_t x1, const uint16_t y1, const uint16_t z1,
const uint16_t x2, const uint16_t y2, const uint16_t z2)
{
if (!d->Started)
return -1;
Process *p = d->owner;
uint16_t coords[3];
uint32_t size = d->p_cre->size();
while (uint32_t(index) < size)
*/
// no jobs for now...
{
// read pointer from vector at position
uint32_t temp = d->p_cre->at(index);
p->read (temp + d->creatures.pos_offset, 3 * sizeof (uint16_t), (uint8_t *) &coords);
if (coords[0] >= x1 && coords[0] < x2)
{
if (coords[1] >= y1 && coords[1] < y2)
{
if (coords[2] >= z1 && coords[2] < z2)
{
ReadCreature (index, furball);
return index;
}
}
}
index++;
furball.current_job.active = false;
}
return -1;
}
int32_t Creatures::FindIndexById(int32_t creature_id)
{
if (!d->Started || !d->Ft_basic)
if (!d->Started)
return -1;
if (!d->IdMapReady)
{
d->IdMap.clear();
Process * p = d->owner;
Private::t_offsets &offs = d->creatures;
uint32_t size = d->p_cre->size();
uint32_t size = creatures->size();
for (uint32_t index = 0; index < size; index++)
{
uint32_t temp = d->p_cre->at(index);
int32_t id = p->readDWord (temp + offs.id_offset);
df_creature * temp = creatures->at(index);
int32_t id = temp->id;
d->IdMap[id] = index;
}
}
@ -459,7 +366,7 @@ int32_t Creatures::FindIndexById(int32_t creature_id)
else
return it->second;
}
/*
bool Creatures::WriteLabors(const uint32_t index, uint8_t labors[NUM_CREATURE_LABORS])
{
if(!d->Started || !d->Ft_advanced) return false;
@ -665,7 +572,7 @@ bool Creatures::WritePregnancy(const uint32_t index, const uint32_t pregTimer)
p->writeDWord(temp + d->creatures.pregnancy_offset, pregTimer);
return true;
}
*/
uint32_t Creatures::GetDwarfRaceIndex()
{
if(!d->Inited) return 0;
@ -688,7 +595,7 @@ bool Creatures::getCurrentCursorCreature(uint32_t & creature_index)
return true;
}
*/
/*
bool Creatures::ReadJob(const t_creature * furball, vector<t_material> & mat)
{
unsigned int i;
@ -709,67 +616,56 @@ bool Creatures::ReadJob(const t_creature * furball, vector<t_material> & mat)
}
return true;
}
bool Creatures::ReadInventoryIdx(const uint32_t index, std::vector<uint32_t> & item)
*/
bool Creatures::ReadInventoryByIdx(const uint32_t index, std::vector<t_item *> & item)
{
if(!d->Started || !d->Ft_inventory) return false;
uint32_t temp = d->p_cre->at (index);
return this->ReadInventoryPtr(temp, item);
if(!d->Started) return false;
if(index >= creatures->size()) return false;
df_creature * temp = creatures->at(index);
return this->ReadInventoryByPtr(temp, item);
}
bool Creatures::ReadInventoryPtr(const uint32_t temp, std::vector<uint32_t> & item)
bool Creatures::ReadInventoryByPtr(const df_creature * temp, std::vector<t_item *> & items)
{
unsigned int i;
if(!d->Started || !d->Ft_inventory) return false;
Process * p = d->owner;
DfVector <uint32_t> citem(temp + d->creatures.inventory_offset);
if(citem.size() == 0)
return false;
item.resize(citem.size());
for(i=0;i<citem.size();i++)
item[i] = p->readDWord(citem[i]);
if(!d->Started) return false;
items = temp->inventory;
return true;
}
bool Creatures::ReadOwnedItemsIdx(const uint32_t index, std::vector<int32_t> & item)
bool Creatures::ReadOwnedItemsByIdx(const uint32_t index, std::vector<int32_t> & item)
{
if(!d->Started || !d->Ft_owned_items) return false;
uint32_t temp = d->p_cre->at (index);
return this->ReadOwnedItemsPtr(temp, item);
if(!d->Started ) return false;
if(index >= creatures->size()) return false;
df_creature * temp = creatures->at(index);
return this->ReadOwnedItemsByPtr(temp, item);
}
bool Creatures::ReadOwnedItemsPtr(const uint32_t temp, std::vector<int32_t> & item)
bool Creatures::ReadOwnedItemsByPtr(const df_creature * temp, std::vector<int32_t> & items)
{
unsigned int i;
if(!d->Started || !d->Ft_owned_items) return false;
Process * p = d->owner;
DfVector <int32_t> citem(temp + d->creatures.owned_items_offset);
if(citem.size() == 0)
return false;
item.resize(citem.size());
for(i=0;i<citem.size();i++)
item[i] = citem[i];
if(!d->Started) return false;
items = temp->owned_items;
return true;
}
bool Creatures::RemoveOwnedItemIdx(const uint32_t index, int32_t id)
bool Creatures::RemoveOwnedItemByIdx(const uint32_t index, int32_t id)
{
if(!d->Started || !d->Ft_owned_items)
if(!d->Started)
{
cerr << "!d->Started || !d->Ft_owned_items FAIL" << endl;
cerr << "!d->Started FAIL" << endl;
return false;
}
uint32_t temp = d->p_cre->at (index);
return this->RemoveOwnedItemPtr(temp, id);
df_creature * temp = creatures->at (index);
return this->RemoveOwnedItemByPtr(temp, id);
}
bool Creatures::RemoveOwnedItemPtr(const uint32_t temp, int32_t id)
bool Creatures::RemoveOwnedItemByPtr(df_creature * temp, int32_t id)
{
if(!d->Started || !d->Ft_owned_items) return false;
if(!d->Started) return false;
Process * p = d->owner;
vector <int32_t> & vec = temp->owned_items;
vec.erase(std::remove(vec.begin(), vec.end(), id), vec.end());
/*
DfVector <int32_t> citem(temp + d->creatures.owned_items_offset);
for (unsigned i = 0; i < citem.size(); i++) {
@ -778,15 +674,12 @@ bool Creatures::RemoveOwnedItemPtr(const uint32_t temp, int32_t id)
if (!citem.remove(i--))
return false;
}
*/
return true;
}
void Creatures::CopyNameTo(t_creature &creature, uint32_t address)
void Creatures::CopyNameTo(df_creature * creature, df_name * target)
{
Private::t_offsets &offs = d->creatures;
if(d->Ft_basic)
d->trans->copyName(creature.origin + offs.name_offset, address);
d->trans->copyName(&creature->name, target);
}

@ -655,7 +655,7 @@ bool Items::removeItemOwner(dfh_item &item, Creatures *creatures)
int32_t & oid = p_refs[i]->value;
int32_t ix = creatures->FindIndexById(oid);
if (ix < 0 || !creatures->RemoveOwnedItemIdx(ix, item.base->id))
if (ix < 0 || !creatures->RemoveOwnedItemByIdx(ix, item.base->id))
{
cerr << "RemoveOwnedItemIdx: CREATURE " << ix << " ID " << item.base->id << " FAILED!" << endl;
return false;

@ -168,7 +168,7 @@ bool Translation::InitReadNames()
return true;
}
bool Translation::readName(t_name & name, uint32_t address)
bool Translation::readName(t_name & name, df_name * source)
{
Core & c = Core::getInstance();
Process * p = c.p;
@ -180,36 +180,35 @@ bool Translation::readName(t_name & name, uint32_t address)
{
if(!InitReadNames()) return false;
}
p->readSTLString(address + d->name_firstname_offset , name.first_name, 128);
p->readSTLString(address + d->name_nickname_offset , name.nickname, 128);
p->read(address + d->name_words_offset, 7*4, (uint8_t *)name.words);
p->read(address + d->name_parts_offset, 7*2, (uint8_t *)name.parts_of_speech);
name.language = p->readDWord(address + d->name_language_offset);
name.has_name = p->readByte(address + d->name_set_offset);
strncpy(name.first_name,source->first_name.c_str(),127);
strncpy(name.nickname,source->nick_name.c_str(),127);
memcpy(&name.parts_of_speech, &source->parts_of_speech, sizeof (source->parts_of_speech));
memcpy(&name.words, &source->words, sizeof (source->words));
name.language = source->language;
name.has_name = source->has_name;
return true;
}
bool Translation::copyName(uint32_t address, uint32_t target)
bool Translation::copyName(df_name * source, df_name * target)
{
uint8_t buf[28];
if (address == target)
if (source == target)
return true;
Core & c = Core::getInstance();
Process * p = c.p;
p->copySTLString(address + d->name_firstname_offset, target + d->name_firstname_offset);
p->copySTLString(address + d->name_nickname_offset, target + d->name_nickname_offset);
p->read(address + d->name_words_offset, 7*4, buf);
p->write(target + d->name_words_offset, 7*4, buf);
p->read(address + d->name_parts_offset, 7*2, buf);
p->write(target + d->name_parts_offset, 7*2, buf);
p->writeDWord(target + d->name_language_offset, p->readDWord(address + d->name_language_offset));
p->writeByte(target + d->name_set_offset, p->readByte(address + d->name_set_offset));
target->first_name = source->first_name;
target->nick_name = source->nick_name;
target->has_name = source->has_name;
target->language = source->language;
memcpy(&target->parts_of_speech, &source->parts_of_speech, sizeof (source->parts_of_speech));
memcpy(&target->words, &source->words, sizeof (source->words));
target->unknown = source->unknown;
return true;
}
string Translation::TranslateName(const t_name &name, bool inEnglish)
string Translation::TranslateName(const df_name * name, bool inEnglish)
{
string out;
assert (d->Started);
@ -218,25 +217,25 @@ string Translation::TranslateName(const t_name &name, bool inEnglish)
if(!inEnglish)
{
if(name.words[0] >=0 || name.words[1] >=0)
if(name->words[0] >=0 || name->words[1] >=0)
{
if(name.words[0]>=0) out.append(d->dicts.foreign_languages[name.language][name.words[0]]);
if(name.words[1]>=0) out.append(d->dicts.foreign_languages[name.language][name.words[1]]);
if(name->words[0]>=0) out.append(d->dicts.foreign_languages[name->language][name->words[0]]);
if(name->words[1]>=0) out.append(d->dicts.foreign_languages[name->language][name->words[1]]);
out[0] = toupper(out[0]);
}
if(name.words[5] >=0)
if(name->words[5] >=0)
{
string word;
for(int i=2;i<=5;i++)
if(name.words[i]>=0) word.append(d->dicts.foreign_languages[name.language][name.words[i]]);
if(name->words[i]>=0) word.append(d->dicts.foreign_languages[name->language][name->words[i]]);
word[0] = toupper(word[0]);
if(out.length() > 0) out.append(" ");
out.append(word);
}
if(name.words[6] >=0)
if(name->words[6] >=0)
{
string word;
word.append(d->dicts.foreign_languages[name.language][name.words[6]]);
word.append(d->dicts.foreign_languages[name->language][name->words[6]]);
word[0] = toupper(word[0]);
if(out.length() > 0) out.append(" ");
out.append(word);
@ -244,13 +243,13 @@ string Translation::TranslateName(const t_name &name, bool inEnglish)
}
else
{
if(name.words[0] >=0 || name.words[1] >=0)
if(name->words[0] >=0 || name->words[1] >=0)
{
if(name.words[0]>=0) out.append(d->dicts.translations[name.parts_of_speech[0]+1][name.words[0]]);
if(name.words[1]>=0) out.append(d->dicts.translations[name.parts_of_speech[1]+1][name.words[1]]);
if(name->words[0]>=0) out.append(d->dicts.translations[name->parts_of_speech[0]+1][name->words[0]]);
if(name->words[1]>=0) out.append(d->dicts.translations[name->parts_of_speech[1]+1][name->words[1]]);
out[0] = toupper(out[0]);
}
if(name.words[5] >=0)
if(name->words[5] >=0)
{
if(out.length() > 0)
out.append(" the");
@ -259,22 +258,22 @@ string Translation::TranslateName(const t_name &name, bool inEnglish)
string word;
for(int i=2;i<=5;i++)
{
if(name.words[i]>=0)
if(name->words[i]>=0)
{
word = d->dicts.translations[name.parts_of_speech[i]+1][name.words[i]];
word = d->dicts.translations[name->parts_of_speech[i]+1][name->words[i]];
word[0] = toupper(word[0]);
out.append(" " + word);
}
}
}
if(name.words[6] >=0)
if(name->words[6] >=0)
{
if(out.length() > 0)
out.append(" of");
else
out.append("Of");
string word;
word.append(d->dicts.translations[name.parts_of_speech[6]+1][name.words[6]]);
word.append(d->dicts.translations[name->parts_of_speech[6]+1][name->words[6]]);
word[0] = toupper(word[0]);
out.append(" " + word);
}

@ -178,14 +178,12 @@ DFhackCExport command_result df_cleanowned (Core * c, vector <string> & paramete
if (owner_index >= 0)
{
DFHack::t_creature temp;
Creatures->ReadCreature(owner_index,temp);
temp.name.first_name[0] = toupper(temp.name.first_name[0]);
info = temp.name.first_name;
if (temp.name.nickname[0])
info += std::string(" '") + temp.name.nickname + "'";
DFHack::df_creature * temp = Creatures->GetCreature(owner_index);
info = temp->name.first_name;
if (!temp->name.nick_name.empty())
info += std::string(" '") + temp->name.nick_name + "'";
info += " ";
info += Tran->TranslateName(temp.name,false);
info += Tran->TranslateName(&temp->name,false);
c->con.print(", owner %s", info.c_str());
}

@ -25,6 +25,7 @@ DFhackCExport command_result ktimer (Core * c, vector <string> & parameters);
DFhackCExport command_result bflags (Core * c, vector <string> & parameters);
DFhackCExport command_result trackmenu (Core * c, vector <string> & parameters);
DFhackCExport command_result mapitems (Core * c, vector <string> & parameters);
DFhackCExport command_result test_creature_offsets (Core * c, vector <string> & parameters);
DFhackCExport const char * plugin_name ( void )
{
@ -39,6 +40,7 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand>
commands.push_back(PluginCommand("blockflags","Look up block flags",bflags));
commands.push_back(PluginCommand("trackmenu","Track menu ID changes (toggle).",trackmenu));
commands.push_back(PluginCommand("mapitems","Check item ids under cursor against item ids in map block.",mapitems));
commands.push_back(PluginCommand("test_creature_offsets","Bleh.",test_creature_offsets));
return CR_OK;
}
@ -287,3 +289,15 @@ DFhackCExport command_result kittens (Core * c, vector <string> & parameters)
color = Console::COLOR_BLUE;
}
}
#include "dfhack/modules/Creatures.h"
#include "dfhack/VersionInfo.h"
#include <stddef.h>
command_result test_creature_offsets(Core* c, vector< string >& parameters)
{
uint32_t off_vinfo = c->vinfo->getGroup("Creatures")->getGroup("creature")->/*getGroup("advanced")->*/getOffset("custom_profession");
uint32_t off_struct = offsetof(df_creature,custom_profession);
c->con.print("Struct 0x%x, vinfo 0x%x\n", off_struct, off_vinfo);
return CR_OK;
};

@ -1 +1 @@
Subproject commit 462f6f9767c0676c06b78ba2acab48a60a3963f5
Subproject commit c140ed8d6dbe05854ee1499540814d5f358a960a