Merge remote-tracking branch 'quietust/master'

develop
Mike Stewart 2012-01-24 12:27:38 -08:00
commit e68cdee95b
27 changed files with 703 additions and 750 deletions

@ -0,0 +1,34 @@
##############################
# Generic dwarfmode bindings #
##############################
keybinding add Ctrl-W twaterlvl
# with cursor:
keybinding add Ctrl-V vdig
keybinding add Ctrl-Shift-V "vdig x"
keybinding add Ctrl-C spotclean
keybinding add Ctrl-Shift-K autodump-destroy-here
# any item:
keybinding add Ctrl-K autodump-destroy-item
#############################
# Context-specific bindings #
#############################
# q->stockpile; p
keybinding add Alt-P copystock
# q->workshop
keybinding add Ctrl-D job-duplicate
# materials: q->workshop; b->select items
keybinding add Shift-A "job-material ALUNITE"
keybinding add Shift-M "job-material MICROCLINE"
keybinding add Shift-D "job-material DACITE"
keybinding add Shift-R "job-material RHYOLITE"
keybinding add Shift-I "job-material CINNABAR"
keybinding add Shift-B "job-material COBALTITE"
keybinding add Shift-O "job-material OBSIDIAN"
keybinding add Shift-G "job-material GLASS_GREEN"

@ -1088,13 +1088,9 @@ TYPE * Core::get##TYPE() \
return s_mods.p##TYPE;\
}
MODULE_GETTER(Units);
MODULE_GETTER(Engravings);
MODULE_GETTER(Gui);
MODULE_GETTER(World);
MODULE_GETTER(Materials);
MODULE_GETTER(Translation);
MODULE_GETTER(Vegetation);
MODULE_GETTER(Constructions);
MODULE_GETTER(Notes);
MODULE_GETTER(Graphic);

@ -52,13 +52,9 @@ namespace DFHack
{
class Process;
class Module;
class Units;
class Engravings;
class Gui;
class World;
class Materials;
class Translation;
class Vegetation;
class Constructions;
class Notes;
class VersionInfo;
@ -97,20 +93,12 @@ namespace DFHack
/// Is everything OK?
bool isValid(void) { return !errorstate; }
/// get the creatures module
Units * getUnits();
/// get the engravings module
Engravings * getEngravings();
/// get the gui module
Gui * getGui();
/// get the world module
World * getWorld();
/// get the materials module
Materials * getMaterials();
/// get the translation module
Translation * getTranslation();
/// get the vegetation module
Vegetation * getVegetation();
/// get the constructions module
Constructions * getConstructions();
/// get the notes module
@ -161,13 +149,9 @@ namespace DFHack
// Module storage
struct
{
Units * pUnits;
Engravings * pEngravings;
Gui * pGui;
World * pWorld;
Materials * pMaterials;
Translation * pTranslation;
Vegetation * pVegetation;
Constructions * pConstructions;
Notes * pNotes;
Graphic * pGraphic;

@ -30,14 +30,10 @@ distribution.
namespace DFHack
{
class Module;
Module* createUnits();
Module* createEngravings();
Module* createGui();
Module* createWorld();
Module* createMaterials();
Module* createTranslation();
Module* createVegetation();
Module* createBuildings();
Module* createConstructions();
Module* createNotes();
Module* createGraphic();

@ -29,94 +29,22 @@ distribution.
* DF engravings
*/
#include "Export.h"
#include "Module.h"
#include "DataDefs.h"
#include "df/engraving.h"
/**
* \defgroup grp_engraving Engraving module parts
* @ingroup grp_modules
*/
namespace DFHack
{
/**
* engraving flags
* \ingroup grp_engraving
*/
struct flg_engraving
{
// there are 9 directions an engraving can have.
// unfortunately, a tile can't be engraved from more than one direction by the game
unsigned int floor : 1; // engraved on a floor 0x1
unsigned int west : 1; // engraved from west 0x2
unsigned int east : 1; // engraved from east 0x4
unsigned int north : 1; // engraved from north 0x8
unsigned int south : 1; // engraved from south 0x10
unsigned int hidden : 1; // hide the engraving 0x20
unsigned int northwest : 1; // engraved from... 0x40
unsigned int northeast : 1; // engraved from... 0x80
unsigned int southwest : 1; // engraved from... 0x100
unsigned int southeast : 1; // engraved from... 0x200
unsigned int rest : 22; // probably unused
};
/**
* type the engraving is made of
* \ingroup grp_engraving
*/
struct t_engraving
{
//0
int32_t artistIdx; /*!< Index of the artist in some global vector */
// 4
int32_t unknownIdx; // likes to stay -1
// 8
uint32_t unknown1; // likes to stay 1
// C
uint16_t x; /*!< X coordinate */
uint16_t y; /*!< Y coordinate */
// 10
uint16_t z; /*!< Z coordinate */
uint16_t padding; /*!< Could be used for hiding values. */
// 14
flg_engraving flags; // 0x20 = hide symbol
// 18
uint8_t display_character; // really? 4 bytes for that?
uint8_t padding2[3];
// 1C
uint32_t type; // possibly an enum, decides what vectors to use for imagery
// 20
int16_t subtype_idx; // index in a vector kind of deal related to previous value
uint16_t quality; // from 0 to 5
// 24
uint32_t unknown2;
// 28 = length
};
/**
* structure for holding a DF engraving
* \ingroup grp_engraving
*/
struct dfh_engraving
{
t_engraving s;
t_engraving * origin;
};
/**
* The Engravings module - allows reading engravings :D
* \ingroup grp_modules
* \ingroup grp_engraving
*/
class DFHACK_EXPORT Engravings : public Module
{
public:
Engravings();
~Engravings();
bool Start(uint32_t & numEngravings);
bool Read (const uint32_t index, dfh_engraving & engr);
bool Write (const dfh_engraving & engr);
bool Finish();
private:
struct Private;
Private *d;
};
namespace Simple
{
namespace Engravings
{
DFHACK_EXPORT bool isValid();
DFHACK_EXPORT uint32_t getCount();
DFHACK_EXPORT df::engraving *getEngraving (const int32_t index);
}
}
}
#endif

@ -90,7 +90,6 @@ namespace DFHack
class Context;
class DFContextShared;
class Units;
/**
* Type for holding an item read from DF
@ -133,12 +132,14 @@ DFHACK_EXPORT bool writeItem(const dfh_item & item);
DFHACK_EXPORT std::string getItemClass(const df::item * item);
/// who owns this item we already read?
DFHACK_EXPORT int32_t getItemOwnerID(const df::item * item);
DFHACK_EXPORT df::unit *getItemOwner(const df::item * item);
/// which item is it contained in?
DFHACK_EXPORT int32_t getItemContainerID(const df::item * item);
DFHACK_EXPORT df::item *getItemContainer(const df::item * item);
/// which items does it contain?
DFHACK_EXPORT bool getContainedItems(const df::item * item, /*output*/ std::vector<int32_t> &items);
/// wipe out the owner records
DFHACK_EXPORT bool removeItemOwner(df::item * item, Units *creatures);
DFHACK_EXPORT bool removeItemOwner(df::item * item);
/// read item references, filtered by class
DFHACK_EXPORT bool readItemRefs(const df::item * item, const df::general_ref_type type,
/*output*/ std::vector<int32_t> &values);

@ -74,6 +74,7 @@ namespace DFHack
df::material *material;
enum Mode {
None,
Builtin,
Inorganic,
Creature,
@ -94,6 +95,15 @@ namespace DFHack
bool isValid() const { return material != NULL; }
bool isNone() const { return mode == None; }
bool isBuiltin() const { return mode == Builtin; }
bool isInorganic() const { return mode == Inorganic; }
bool isCreature() const { return mode == Creature; }
bool isPlant() const { return mode == Plant; }
bool isAnyInorganic() const { return type == 0; }
bool isInorganicWildcard() const { return isAnyInorganic() && isBuiltin(); }
bool decode(int16_t type, int32_t index = -1);
bool decode(df::item *item);
bool decode(const df::material_vec_ref &vr, int idx);
@ -110,6 +120,7 @@ namespace DFHack
bool findPlant(const std::string &token, const std::string &subtoken);
bool findCreature(const std::string &token, const std::string &subtoken);
std::string getToken();
std::string toString(uint16_t temp = 10015, bool named = true);
bool isAnyCloth();

@ -33,51 +33,28 @@ distribution.
#include "Export.h"
#include "Module.h"
#include "Types.h"
#include "DataDefs.h"
#include "df/language_word.h"
#include "df/language_translation.h"
#include "df/language_name.h"
namespace DFHack
{
namespace Simple
{
namespace Translation
{
// simple check to make sure if there's actual language data present
DFHACK_EXPORT bool IsValid ();
class DFContextShared;
/**
* \ingroup grp_translation
*/
typedef std::vector< std::vector<std::string> > DFDict;
/**
* \ingroup grp_translation
*/
typedef struct
{
DFDict translations;
DFDict foreign_languages;
} Dicts;
/**
* The Tanslation module
* \ingroup grp_translation
* \ingroup grp_maps
*/
class DFHACK_EXPORT Translation : public Module
{
public:
Translation();
~Translation();
bool Start();
bool Finish();
// Get pointer to the two dictionary structures
Dicts * getDicts();
// names, used by a few other modules.
bool InitReadNames();
bool readName(t_name & name, df::language_name * address);
bool copyName(df::language_name * address, df::language_name * target);
// translate a name using the loaded dictionaries
std::string TranslateName(const df::language_name * name, bool inEnglish = true);
// names, used by a few other modules.
DFHACK_EXPORT bool readName(t_name & name, df::language_name * address);
DFHACK_EXPORT bool copyName(df::language_name * address, df::language_name * target);
private:
struct Private;
Private *d;
};
// translate a name using the loaded dictionaries
DFHACK_EXPORT std::string TranslateName (const df::language_name * name, bool inEnglish = true);
}
}
}
#endif

@ -26,11 +26,11 @@ distribution.
#ifndef CL_MOD_CREATURES
#define CL_MOD_CREATURES
/*
* Creatures
*/
* Creatures
*/
#include "Export.h"
#include "Module.h"
#include "modules/Items.h"
#include "DataDefs.h"
#include "df/unit.h"
/**
@ -39,234 +39,161 @@ distribution.
*/
namespace DFHack
{
// FIXME: WTF IS THIS SHIT?
/*
struct t_labor
{
string name;
uint8_t value;
t_labor() {
value =0;
}
t_labor(const t_labor & b){
name=b.name;
value=b.value;
}
t_labor & operator=(const t_labor &b){
name=b.name;
value=b.value;
return *this;
}
};
struct t_skill
{
string name;
uint16_t id;
namespace Simple
{
namespace Units
{
/**
* \ingroup grp_units
*/
struct t_skill
{
uint32_t id;
uint32_t rating;
uint32_t experience;
uint16_t rating;
t_skill(){
id=rating=0;
experience=0;
}
t_skill(const t_skill & b)
{
name=b.name;
id=b.id;
experience=b.experience;
rating=b.rating;
}
t_skill & operator=(const t_skill &b)
{
name=b.name;
id=b.id;
experience=b.experience;
rating=b.rating;
return *this;
}
};
struct t_trait
{
uint16_t value;
string displayTxt;
string name;
t_trait(){
value=0;
}
t_trait(const t_trait &b)
{
name=b.name;
displayTxt=b.displayTxt;
value=b.value;
}
t_trait & operator=(const t_trait &b)
{
name=b.name;
displayTxt=b.displayTxt;
value=b.value;
return *this;
}
};
*/
/**
* \ingroup grp_units
*/
struct t_skill
{
uint32_t id;
uint32_t rating;
uint32_t experience;
};
/**
* \ingroup grp_units
*/
struct t_job
{
bool active;
uint32_t jobId;
uint8_t jobType;
uint32_t occupationPtr;
};
/**
* \ingroup grp_units
*/
struct t_like
{
int16_t type;
int16_t itemClass;
int16_t itemIndex;
t_matglossPair material;
bool active;
uint32_t mystery;
};
// FIXME: THIS IS VERY, VERY BAD.
#define NUM_CREATURE_LABORS 96
#define NUM_CREATURE_TRAITS 30
#define NUM_CREATURE_MENTAL_ATTRIBUTES 13
#define NUM_CREATURE_PHYSICAL_ATTRIBUTES 6
/**
* Structure for holding a copy of a DF unit's soul
* \ingroup grp_units
*/
struct t_soul
{
uint8_t numSkills;
t_skill skills[256];
//uint8_t numLikes;
//t_like likes[32];
uint16_t traits[NUM_CREATURE_TRAITS];
t_attrib analytical_ability;
t_attrib focus;
t_attrib willpower;
t_attrib creativity;
t_attrib intuition;
t_attrib patience;
t_attrib memory;
t_attrib linguistic_ability;
t_attrib spatial_sense;
t_attrib musicality;
t_attrib kinesthetic_sense;
t_attrib empathy;
t_attrib social_awareness;
};
#define MAX_COLORS 15
struct df_unit;
/**
* Structure for holding a limited copy of a DF unit
* \ingroup grp_units
*/
struct t_unit
{
df::unit * origin;
uint16_t x;
uint16_t y;
uint16_t z;
uint32_t race;
int32_t civ;
df::unit_flags1 flags1;
df::unit_flags2 flags2;
df::unit_flags3 flags3;
t_name name;
int16_t mood;
int16_t mood_skill;
t_name artifact_name;
uint8_t profession;
std::string custom_profession;
// enabled labors
uint8_t labors[NUM_CREATURE_LABORS];
t_job current_job;
uint32_t happiness;
uint32_t id;
t_attrib strength;
t_attrib agility;
t_attrib toughness;
t_attrib endurance;
t_attrib recuperation;
t_attrib disease_resistance;
int32_t squad_leader_id;
uint8_t sex;
uint16_t caste;
uint32_t pregnancy_timer; //Countdown timer to giving birth
//bool has_default_soul;
//t_soul defaultSoul;
uint32_t nbcolors;
uint32_t color[MAX_COLORS];
int32_t birth_year;
uint32_t birth_time;
};
};
/**
* \ingroup grp_units
*/
struct t_job
{
bool active;
uint32_t jobId;
uint8_t jobType;
uint32_t occupationPtr;
};
/**
* \ingroup grp_units
*/
struct t_like
{
int16_t type;
int16_t itemClass;
int16_t itemIndex;
t_matglossPair material;
bool active;
uint32_t mystery;
};
// FIXME: THIS IS VERY, VERY BAD.
#define NUM_CREATURE_LABORS 96
#define NUM_CREATURE_TRAITS 30
#define NUM_CREATURE_MENTAL_ATTRIBUTES 13
#define NUM_CREATURE_PHYSICAL_ATTRIBUTES 6
/**
* Structure for holding a copy of a DF unit's soul
* \ingroup grp_units
*/
struct t_soul
{
uint8_t numSkills;
t_skill skills[256];
//uint8_t numLikes;
//t_like likes[32];
uint16_t traits[NUM_CREATURE_TRAITS];
t_attrib analytical_ability;
t_attrib focus;
t_attrib willpower;
t_attrib creativity;
t_attrib intuition;
t_attrib patience;
t_attrib memory;
t_attrib linguistic_ability;
t_attrib spatial_sense;
t_attrib musicality;
t_attrib kinesthetic_sense;
t_attrib empathy;
t_attrib social_awareness;
};
#define MAX_COLORS 15
struct df_unit;
/**
* Structure for holding a limited copy of a DF unit
* \ingroup grp_units
*/
struct t_unit
{
df::unit * origin;
uint16_t x;
uint16_t y;
uint16_t z;
uint32_t race;
int32_t civ;
df::unit_flags1 flags1;
df::unit_flags2 flags2;
df::unit_flags3 flags3;
t_name name;
int16_t mood;
int16_t mood_skill;
t_name artifact_name;
uint8_t profession;
std::string custom_profession;
// enabled labors
uint8_t labors[NUM_CREATURE_LABORS];
t_job current_job;
uint32_t happiness;
uint32_t id;
t_attrib strength;
t_attrib agility;
t_attrib toughness;
t_attrib endurance;
t_attrib recuperation;
t_attrib disease_resistance;
int32_t squad_leader_id;
uint8_t sex;
uint16_t caste;
uint32_t pregnancy_timer; //Countdown timer to giving birth
//bool has_default_soul;
//t_soul defaultSoul;
uint32_t nbcolors;
uint32_t color[MAX_COLORS];
int32_t birth_year;
uint32_t birth_time;
};
/**
* The Creatures module - allows reading all non-vermin creatures and their properties
* \ingroup grp_modules
* \ingroup grp_units
*/
class DFHACK_EXPORT Units : public Module
{
public:
Units();
~Units();
bool Start( uint32_t & numCreatures );
bool Finish();
/**
* The Creatures module - allows reading all non-vermin creatures and their properties
* \ingroup grp_modules
* \ingroup grp_units
*/
/* 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 GetCreatureInBox(const int32_t index, df::unit ** 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);
df::unit * GetCreature(const int32_t index);
void CopyCreature(df::unit * source, t_unit & target);
DFHACK_EXPORT bool isValid();
bool ReadJob(const df::unit * unit, std::vector<t_material> & mat);
/* 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)
DFHACK_EXPORT int32_t GetCreatureInBox(const int32_t index, df::unit ** 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);
DFHACK_EXPORT df::unit * GetCreature(const int32_t index);
DFHACK_EXPORT void CopyCreature(df::unit * source, t_unit & target);
bool ReadInventoryByIdx(const uint32_t index, std::vector<df::item *> & item);
bool ReadInventoryByPtr(const df::unit * unit, std::vector<df::item *> & item);
DFHACK_EXPORT bool ReadJob(const df::unit * unit, std::vector<t_material> & mat);
bool ReadOwnedItemsByIdx(const uint32_t index, std::vector<int32_t> & item);
bool ReadOwnedItemsByPtr(const df::unit * unit, std::vector<int32_t> & item);
DFHACK_EXPORT bool ReadInventoryByIdx(const uint32_t index, std::vector<df::item *> & item);
DFHACK_EXPORT bool ReadInventoryByPtr(const df::unit * unit, std::vector<df::item *> & item);
int32_t FindIndexById(int32_t id);
DFHACK_EXPORT bool ReadOwnedItemsByIdx(const uint32_t index, std::vector<int32_t> & item);
DFHACK_EXPORT bool ReadOwnedItemsByPtr(const df::unit * unit, std::vector<int32_t> & item);
/* Getters */
uint32_t GetDwarfRaceIndex ( void );
int32_t GetDwarfCivId ( void );
DFHACK_EXPORT int32_t FindIndexById(int32_t id);
void CopyNameTo(df::unit *creature, df::language_name * target);
/* Getters */
DFHACK_EXPORT uint32_t GetDwarfRaceIndex ( void );
DFHACK_EXPORT int32_t GetDwarfCivId ( void );
bool RemoveOwnedItemByIdx(const uint32_t index, int32_t id);
bool RemoveOwnedItemByPtr(df::unit * unit, int32_t id);
DFHACK_EXPORT void CopyNameTo(df::unit *creature, df::language_name * target);
private:
struct Private;
Private *d;
};
DFHACK_EXPORT bool RemoveOwnedItemByIdx(const uint32_t index, int32_t id);
DFHACK_EXPORT bool RemoveOwnedItemByPtr(df::unit * unit, int32_t id);
}
}
}
#endif

@ -31,27 +31,21 @@ distribution.
*/
#include "Export.h"
#include "Module.h"
#include "Types.h"
#include "DataDefs.h"
#include "df/plant.h"
namespace DFHack
{
/**
* \ingroup grp_vegetation
*/
const uint32_t sapling_to_tree_threshold = 0x1D880;
/**
* The Vegetation module
* \ingroup grp_vegetation
* \ingroup grp_modules
*/
class DFHACK_EXPORT Vegetation : public Module
{
public:
Vegetation();
~Vegetation();
bool Finish(){return true;};
};
namespace Simple
{
namespace Vegetation
{
const uint32_t sapling_to_tree_threshold = 120 * 28 * 12 * 3; // 3 years
DFHACK_EXPORT bool isValid();
DFHACK_EXPORT uint32_t getCount();
DFHACK_EXPORT df::plant *getPlant (const int32_t index);
}
}
}
#endif

@ -33,77 +33,28 @@ using namespace std;
#include "VersionInfo.h"
#include "MemAccess.h"
#include "Types.h"
#include "modules/Engravings.h"
#include "ModuleFactory.h"
#include "Core.h"
using namespace DFHack;
struct Engravings::Private
{
uint32_t engraving_vector;
vector <t_engraving *> * p_engr;
Process * owner;
bool Inited;
bool Started;
};
Module* DFHack::createEngravings()
{
return new Engravings();
}
Engravings::Engravings()
{
Core & c = Core::getInstance();
d = new Private;
d->owner = c.p;
d->Inited = d->Started = false;
d->p_engr = (decltype(d->p_engr)) c.vinfo->getGroup("Engravings")->getAddress ("vector");
d->Inited = true;
}
Engravings::~Engravings()
{
if(d->Started)
Finish();
delete d;
}
bool Engravings::Start(uint32_t & numengravings)
{
if(!d->Inited)
return false;
numengravings = d->p_engr->size();
d->Started = true;
return true;
}
#include "modules/Engravings.h"
#include "df/world.h"
using namespace DFHack;
using namespace DFHack::Simple;
using df::global::world;
bool Engravings::Read (const uint32_t index, dfh_engraving & engraving)
bool Engravings::isValid()
{
if(!d->Started) return false;
// read pointer from vector at position
engraving.s = *d->p_engr->at (index);
// transform
engraving.origin = d->p_engr->at (index);
return true;
return (world->engravings.size() > 0);
}
bool Engravings::Write (const dfh_engraving & engraving)
uint32_t Engravings::getCount()
{
if(!d->Started) return false;
//write engraving to memory
d->owner->write (engraving.origin, sizeof (t_engraving), (uint8_t *) &(engraving.s));
return true;
return world->engravings.size();
}
bool Engravings::Finish()
df::engraving *Engravings::getEngraving(const int32_t index)
{
d->Started = false;
return true;
if (index < 0 || index >= getCount())
return NULL;
return world->engravings[index];
}

@ -29,7 +29,6 @@ distribution.
#include <vector>
#include <map>
#include <set>
#include <cassert>
#include <cstdlib>
using namespace std;

@ -304,7 +304,7 @@ bool ItemTypeInfo::matches(const df::job_item &item, MaterialInfo *mat)
OK(2,blunt);
if (VIRTUAL_CAST_VAR(def, df::itemdef_toolst, custom)) {
df::enum_field<df::tool_uses,int16_t> key(tool_uses::FOOD_STORAGE);
df::tool_uses key(tool_uses::FOOD_STORAGE);
if (linear_index(def->tool_use, key) >= 0)
OK(3,food_storage);
} else {
@ -436,6 +436,17 @@ int32_t Items::getItemOwnerID(const df::item * item)
return -1;
}
df::unit *Items::getItemOwner(const df::item * item)
{
for (uint32_t i = 0; i < item->itemrefs.size(); i++)
{
df::general_ref *ref = item->itemrefs[i];
if (ref->getType() == df::general_ref_type::UNIT_ITEMOWNER)
return ref->getUnit();
}
return NULL;
}
int32_t Items::getItemContainerID(const df::item * item)
{
for (uint32_t i = 0; i < item->itemrefs.size(); i++)
@ -447,6 +458,17 @@ int32_t Items::getItemContainerID(const df::item * item)
return -1;
}
df::item *Items::getItemContainer(const df::item * item)
{
for (uint32_t i = 0; i < item->itemrefs.size(); i++)
{
df::general_ref *ref = item->itemrefs[i];
if (ref->getType() == df::general_ref_type::CONTAINED_IN_ITEM)
return ref->getItem();
}
return NULL;
}
bool Items::getContainedItems(const df::item * item, std::vector<int32_t> &items)
{
return readItemRefs(item, df::general_ref_type::CONTAINS_ITEM, items);
@ -466,7 +488,7 @@ bool Items::readItemRefs(const df::item * item, df::general_ref_type type, std::
return !values.empty();
}
bool Items::removeItemOwner(df::item * item, Units *creatures)
bool Items::removeItemOwner(df::item * item)
{
for (uint32_t i = 0; i < item->itemrefs.size(); i++)
{
@ -476,7 +498,7 @@ bool Items::removeItemOwner(df::item * item, Units *creatures)
df::unit *unit = ref->getUnit();
if (unit == NULL || !creatures->RemoveOwnedItemByPtr(unit, item->id))
if (unit == NULL || !Units::RemoveOwnedItemByPtr(unit, item->id))
{
cerr << "RemoveOwnedItemIdx: CREATURE " << ref->getID() << " ID " << item->id << " FAILED!" << endl;
return false;

@ -29,7 +29,6 @@ distribution.
#include <vector>
#include <map>
#include <set>
#include <cassert>
#include <cstdlib>
using namespace std;

@ -95,9 +95,14 @@ bool MaterialInfo::decode(int16_t type, int32_t index)
inorganic = NULL; plant = NULL; creature = NULL;
figure = NULL;
if (type < 0) {
mode = None;
return false;
}
df::world_raws &raws = world->raws;
if (type < 0 || type >= sizeof(raws.mat_table.builtin)/sizeof(void*))
if (type >= sizeof(raws.mat_table.builtin)/sizeof(void*))
return false;
if (index < 0)
@ -159,7 +164,7 @@ bool MaterialInfo::find(const std::string &token)
std::vector<std::string> items;
split_string(&items, token, ":");
if (items[0] == "INORGANIC")
if (items[0] == "INORGANIC" && items.size() > 1)
return findInorganic(vector_get(items,1));
if (items[0] == "CREATURE_MAT" || items[0] == "CREATURE")
return findCreature(vector_get(items,1), vector_get(items,2));
@ -267,12 +272,35 @@ bool MaterialInfo::findCreature(const std::string &token, const std::string &sub
return decode(-1);
}
std::string MaterialInfo::toString(uint16_t temp, bool named)
std::string MaterialInfo::getToken()
{
if (type == -1)
if (isNone())
return "NONE";
if (!material)
return stl_sprintf("INVALID:%d:%d", type, index);
switch (mode) {
case Builtin:
return material->id;
case Inorganic:
return "INORGANIC:" + inorganic->id;
case Creature:
return "CREATURE:" + creature->creature_id + ":" + material->id;
case Plant:
return "PLANT:" + plant->id + ":" + material->id;
default:
return stl_sprintf("INVALID_MODE:%d:%d", type, index);
}
}
std::string MaterialInfo::toString(uint16_t temp, bool named)
{
if (isNone())
return "any";
if (!material)
return stl_sprintf("INVALID %d:%d", type, index);
return stl_sprintf("INVALID:%d:%d", type, index);
df::matter_state state = matter_state::Solid;
if (temp >= material->heat.melting_point)

@ -27,7 +27,6 @@ distribution.
#include <string>
#include <vector>
#include <map>
#include <cassert>
using namespace std;
#include "modules/Translation.h"
@ -38,148 +37,20 @@ using namespace std;
#include "Core.h"
using namespace DFHack;
using namespace DFHack::Simple;
Module* DFHack::createTranslation()
{
return new Translation();
}
struct Translation::Private
{
void * genericAddress;
void * transAddress;
uint32_t word_table_offset;
uint32_t sizeof_string;
#include "DataDefs.h"
#include "df/world.h"
// translation
Dicts dicts;
bool Inited;
bool Started;
// names
uint32_t name_firstname_offset;
uint32_t name_nickname_offset;
uint32_t name_words_offset;
uint32_t name_parts_offset;
uint32_t name_language_offset;
uint32_t name_set_offset;
bool namesInited;
bool namesFailed;
};
Translation::Translation()
{
Core & c = Core::getInstance();
d = new Private;
d->Inited = d->Started = false;
OffsetGroup * OG_Translation = c.vinfo->getGroup("Translations");
OffsetGroup * OG_String = c.vinfo->getGroup("string");
d->genericAddress = OG_Translation->getAddress ("language_vector");
d->transAddress = OG_Translation->getAddress ("translation_vector");
d->word_table_offset = OG_Translation->getOffset ("word_table");
d->sizeof_string = OG_String->getHexValue ("sizeof");
d->Inited = true;
d->namesInited = false;
d->namesFailed = false;
}
using df::global::world;
Translation::~Translation()
bool Translation::IsValid ()
{
if(d->Started)
Finish();
delete d;
}
bool Translation::Start()
{
Core & c = Core::getInstance();
if(!d->Inited)
return false;
Process * p = c.p;
Finish();
vector <char *> & genericVec = *(vector <char *> *) d->genericAddress;
vector <char *> & transVec = *(vector <char *> *) d->transAddress;
DFDict & translations = d->dicts.translations;
DFDict & foreign_languages = d->dicts.foreign_languages;
translations.resize(10);
for (uint32_t i = 0;i < genericVec.size();i++)
{
char * genericNamePtr = genericVec[i];
for(int j=0; j<10;j++)
{
string word = p->readSTLString (genericNamePtr + j * d->sizeof_string);
translations[j].push_back (word);
}
}
foreign_languages.resize(transVec.size());
for (uint32_t i = 0; i < transVec.size();i++)
{
char * transPtr = transVec.at(i);
vector <void *> & trans_names_vec = *(vector <void *> *) (transPtr + d->word_table_offset);
for (uint32_t j = 0;j < trans_names_vec.size();j++)
{
void * transNamePtr = trans_names_vec[j];
string name = p->readSTLString (transNamePtr);
foreign_languages[i].push_back (name);
}
}
d->Started = true;
return true;
}
bool Translation::Finish()
{
d->dicts.foreign_languages.clear();
d->dicts.translations.clear();
d->Started = false;
return true;
}
Dicts * Translation::getDicts()
{
assert(d->Started);
if(d->Started)
return &d->dicts;
return 0;
}
bool Translation::InitReadNames()
{
Core & c = Core::getInstance();
try
{
OffsetGroup * OG = c.vinfo->getGroup("name");
d->name_firstname_offset = OG->getOffset("first");
d->name_nickname_offset = OG->getOffset("nick");
d->name_words_offset = OG->getOffset("second_words");
d->name_parts_offset = OG->getOffset("parts_of_speech");
d->name_language_offset = OG->getOffset("language");
d->name_set_offset = OG->getOffset("has_name");
}
catch(exception &)
{
d->namesFailed = true;
return false;
}
d->namesInited = true;
return true;
return (world->raws.language.words.size() > 0) && (world->raws.language.translations.size() > 0);
}
bool Translation::readName(t_name & name, df::language_name * source)
{
Core & c = Core::getInstance();
Process * p = c.p;
if(d->namesFailed)
{
return false;
}
if(!d->namesInited)
{
if(!InitReadNames()) return false;
}
strncpy(name.first_name,source->first_name.c_str(),127);
strncpy(name.nickname,source->nickname.c_str(),127);
memcpy(&name.parts_of_speech, &source->parts_of_speech, sizeof (source->parts_of_speech));
@ -193,89 +64,92 @@ bool Translation::copyName(df::language_name * source, df::language_name * targe
{
if (source == target)
return true;
Core & c = Core::getInstance();
Process * p = c.p;
target->first_name = source->first_name;
target->nickname = source->nickname;
target->has_name = source->has_name;
for (int i = 0; i < 7; i++)
{
target->words[i] = source->words[i];
target->parts_of_speech[i] = source->parts_of_speech[i];
}
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;
target->has_name = source->has_name;
return true;
}
string Translation::TranslateName(const df::language_name * name, bool inEnglish)
{
string out;
assert (d->Started);
map<string, vector<string> >::const_iterator it;
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(*world->raws.language.translations[name->language]->words[name->words[0]]);
if (name->words[1] >= 0)
out.append(*world->raws.language.translations[name->language]->words[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]]);
for (int i = 2; i <= 5; i++)
if (name->words[i] >= 0)
word.append(*world->raws.language.translations[name->language]->words[name->words[i]]);
word[0] = toupper(word[0]);
if(out.length() > 0) out.append(" ");
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]]);
string word = *world->raws.language.translations[name->language]->words[name->words[6]];
word[0] = toupper(word[0]);
if(out.length() > 0) out.append(" ");
if (out.length() > 0)
out.append(" ");
out.append(word);
}
}
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].value+1][name->words[0]]);
if(name->words[1]>=0) out.append(d->dicts.translations[name->parts_of_speech[1].value+1][name->words[1]]);
if (name->words[0] >= 0)
out.append(world->raws.language.words[name->words[0]]->forms[name->parts_of_speech[0].value]);
if (name->words[1] >= 0)
out.append(world->raws.language.words[name->words[1]]->forms[name->parts_of_speech[1].value]);
out[0] = toupper(out[0]);
}
if(name->words[5] >=0)
if (name->words[5] >= 0)
{
if(out.length() > 0)
if (out.length() > 0)
out.append(" the");
else
out.append("The");
string word;
for(int i=2;i<=5;i++)
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].value+1][name->words[i]];
string word = world->raws.language.words[name->words[i]]->forms[name->parts_of_speech[i].value];
word[0] = toupper(word[0]);
out.append(" " + word);
}
}
}
if(name->words[6] >=0)
if (name->words[6] >= 0)
{
if(out.length() > 0)
if (out.length() > 0)
out.append(" of");
else
out.append("Of");
string word;
word.append(d->dicts.translations[name->parts_of_speech[6].value+1][name->words[6]]);
string word = world->raws.language.words[name->words[6]]->forms[name->parts_of_speech[6].value];
word[0] = toupper(word[0]);
out.append(" " + word);
}
}
return out;
}

@ -33,15 +33,14 @@ distribution.
#include <algorithm>
using namespace std;
#include "VersionInfo.h"
#include "MemAccess.h"
#include "Error.h"
#include "Types.h"
// we connect to those
#include "modules/Materials.h"
#include "modules/Units.h"
#include "modules/Materials.h"
#include "modules/Translation.h"
#include "ModuleFactory.h"
#include "Core.h"
@ -51,67 +50,18 @@ using namespace std;
#include "df/unit_inventory_item.h"
using namespace DFHack;
using namespace DFHack::Simple;
using df::global::world;
using df::global::ui;
struct Units::Private
{
bool Inited;
bool Started;
bool IdMapReady;
std::map<int32_t, int32_t> IdMap;
Process *owner;
Translation * trans;
};
Module* DFHack::createUnits()
bool Units::isValid()
{
return new Units();
}
Units::Units()
{
Core & c = Core::getInstance();
d = new Private;
d->owner = c.p;
VersionInfo * minfo = c.vinfo;
d->Inited = false;
d->Started = false;
d->IdMapReady = false;
d->trans = c.getTranslation();
d->trans->InitReadNames(); // FIXME: throws on error
OffsetGroup *OG_Creatures = minfo->getGroup("Creatures");
d->Inited = true;
}
Units::~Units()
{
if(d->Started)
Finish();
}
bool Units::Start( uint32_t &numcreatures )
{
d->Started = true;
numcreatures = world->units.all.size();
d->IdMap.clear();
d->IdMapReady = false;
return true;
}
bool Units::Finish()
{
d->Started = false;
return true;
return (world->units.all.size() > 0);
}
df::unit * Units::GetCreature (const int32_t index)
{
if(!d->Started) return NULL;
if (!isValid()) return NULL;
// read pointer from vector at position
if(index > world->units.all.size())
@ -124,7 +74,7 @@ int32_t Units::GetCreatureInBox (int32_t index, df::unit ** 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)
if (!isValid())
return -1;
uint32_t size = world->units.all.size();
@ -151,13 +101,13 @@ int32_t Units::GetCreatureInBox (int32_t index, df::unit ** furball,
void Units::CopyCreature(df::unit * source, t_unit & furball)
{
if(!d->Started) return;
if(!isValid()) return;
// read pointer from vector at position
furball.origin = source;
//read creature from memory
// name
d->trans->readName(furball.name, &source->name);
Translation::readName(furball.name, &source->name);
// basic stuff
furball.id = source->id;
@ -183,7 +133,7 @@ void Units::CopyCreature(df::unit * source, t_unit & furball)
// mood stuff
furball.mood = source->mood;
furball.mood_skill = source->job.unk_2f8; // FIXME: really? More like currently used skill anyway.
d->trans->readName(furball.artifact_name, &source->status.artifact_name);
Translation::readName(furball.artifact_name, &source->status.artifact_name);
// labors
memcpy(&furball.labors, &source->status.labors, sizeof(furball.labors));
@ -519,15 +469,16 @@ bool Units::ReadInventoryByIdx(const uint32_t index, std::vector<df::item *> & i
{
if(index >= world->units.all.size()) return false;
df::unit * temp = world->units.all[index];
return this->ReadInventoryByPtr(temp, item);
return ReadInventoryByPtr(temp, item);
}
bool Units::ReadInventoryByPtr(const df::unit * temp, std::vector<df::item *> & items)
bool Units::ReadInventoryByPtr(const df::unit * unit, std::vector<df::item *> & items)
{
if(!d->Started) return false;
if(!isValid()) return false;
if(!unit) return false;
items.clear();
for (uint32_t i = 0; i < temp->inventory.size(); i++)
items.push_back(temp->inventory[i]->item);
for (uint32_t i = 0; i < unit->inventory.size(); i++)
items.push_back(unit->inventory[i]->item);
return true;
}
@ -535,13 +486,14 @@ bool Units::ReadOwnedItemsByIdx(const uint32_t index, std::vector<int32_t> & ite
{
if(index >= world->units.all.size()) return false;
df::unit * temp = world->units.all[index];
return this->ReadOwnedItemsByPtr(temp, item);
return ReadOwnedItemsByPtr(temp, item);
}
bool Units::ReadOwnedItemsByPtr(const df::unit * temp, std::vector<int32_t> & items)
bool Units::ReadOwnedItemsByPtr(const df::unit * unit, std::vector<int32_t> & items)
{
if(!d->Started) return false;
items = temp->owned_items;
if(!isValid()) return false;
if(!unit) return false;
items = unit->owned_items;
return true;
}
@ -549,30 +501,20 @@ bool Units::RemoveOwnedItemByIdx(const uint32_t index, int32_t id)
{
if(index >= world->units.all.size()) return false;
df::unit * temp = world->units.all[index];
return this->RemoveOwnedItemByPtr(temp, id);
return RemoveOwnedItemByPtr(temp, id);
}
bool Units::RemoveOwnedItemByPtr(df::unit * temp, int32_t id)
bool Units::RemoveOwnedItemByPtr(df::unit * unit, int32_t id)
{
if(!d->Started) return false;
Process * p = d->owner;
vector <int32_t> & vec = temp->owned_items;
if(!isValid()) return false;
if(!unit) return false;
vector <int32_t> & vec = unit->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++) {
if (citem[i] != id)
continue;
if (!citem.remove(i--))
return false;
}
*/
return true;
}
void Units::CopyNameTo(df::unit * creature, df::language_name * target)
{
d->trans->copyName(&creature->name, target);
Translation::copyName(&creature->name, target);
}

@ -33,23 +33,29 @@ using namespace std;
#include "VersionInfo.h"
#include "MemAccess.h"
#include "Types.h"
#include "modules/Vegetation.h"
#include "modules/Translation.h"
#include "ModuleFactory.h"
#include "Core.h"
using namespace DFHack;
Module* DFHack::createVegetation()
#include "modules/Vegetation.h"
#include "df/world.h"
using namespace DFHack;
using namespace DFHack::Simple;
using df::global::world;
bool Vegetation::isValid()
{
return new Vegetation();
return (world->plants.all.size() > 0);
}
Vegetation::Vegetation()
uint32_t Vegetation::getCount()
{
return world->plants.all.size();
}
Vegetation::~Vegetation()
df::plant *Vegetation::getPlant(const int32_t index)
{
if (index < 0 || index >= getCount())
return NULL;
return world->plants.all[index];
}

@ -69,6 +69,7 @@ DFHACK_PLUGIN(fixwagons fixwagons.cpp)
DFHACK_PLUGIN(jobutils jobutils.cpp)
DFHACK_PLUGIN(regrass regrass.cpp)
DFHACK_PLUGIN(workflow workflow.cpp)
DFHACK_PLUGIN(showmood showmood.cpp)
#DFHACK_PLUGIN(versionosd versionosd.cpp)
# this is the skeleton plugin. If you want to make your own, make a copy and then change it

@ -122,6 +122,11 @@ DFhackCExport command_result spotclean (Core * c, vector <string> & parameters)
c->con.printerr("The cursor is not active.\n");
return CR_WRONG_USAGE;
}
if (!Maps::IsValid())
{
c->con.printerr("Map is not available.\n");
return CR_FAILURE;
}
df::map_block *block = Maps::getBlockAbs(cursor->x, cursor->y, cursor->z);
if (block == NULL)
{

@ -97,14 +97,9 @@ DFhackCExport command_result df_cleanowned (Core * c, vector <string> & paramete
CoreSuspender suspend(c);
DFHack::Materials *Materials = c->getMaterials();
DFHack::Units *Creatures = c->getUnits();
DFHack::Translation *Tran = c->getTranslation();
uint32_t num_creatures;
bool ok = true;
ok &= Materials->ReadAllMaterials();
ok &= Creatures->Start(num_creatures);
ok &= Tran->Start();
bool ok = Materials->ReadAllMaterials();
c->con.print("Found total %d items.\n", world->items.all.size());
@ -186,24 +181,22 @@ DFhackCExport command_result df_cleanowned (Core * c, vector <string> & paramete
item->getWear()
);
int32_t owner = Items::getItemOwnerID(item);
int32_t owner_index = Creatures->FindIndexById(owner);
df::unit *owner = Items::getItemOwner(item);
std::string info;
if (owner_index >= 0)
if (owner)
{
df::unit * temp = Creatures->GetCreature(owner_index);
info = temp->name.first_name;
if (!temp->name.nickname.empty())
info += std::string(" '") + temp->name.nickname + "'";
info = owner->name.first_name;
if (!owner->name.nickname.empty())
info += std::string(" '") + owner->name.nickname + "'";
info += " ";
info += Tran->TranslateName(&temp->name,false);
info += Translation::TranslateName(&owner->name,false);
c->con.print(", owner %s", info.c_str());
}
if (!dry_run)
{
if (!Items::removeItemOwner(item, Creatures))
if (!Items::removeItemOwner(item))
c->con.print("(unsuccessfully) ");
if (dump)
item->flags.bits.dump = 1;

@ -33,6 +33,12 @@ DFhackCExport command_result df_deramp (Core * c, vector <string> & parameters)
CoreSuspender suspend(c);
if (!Maps::IsValid())
{
c->con.printerr("Map is not available!\n");
return CR_FAILURE;
}
int count = 0;
int countbad = 0;

@ -179,6 +179,13 @@ DFhackCExport command_result df_liquids (Core * c, vector <string> & parameters)
return CR_OK;
}
}
if (!Maps::IsValid())
{
c->con.printerr("Map is not available!\n");
return CR_FAILURE;
}
Brush * brush = new RectangleBrush(1,1);
string brushname = "point";
bool end = false;

@ -222,7 +222,7 @@ DFhackCExport command_result df_grow (Core * c, vector <string> & parameters)
{
if(DFHack::tileShape(map.tiletypeAt(DFHack::DFCoord(x,y,z))) == DFHack::SAPLING_OK)
{
tree->grow_counter = DFHack::sapling_to_tree_threshold;
tree->grow_counter = Vegetation::sapling_to_tree_threshold;
}
break;
}
@ -238,7 +238,7 @@ DFhackCExport command_result df_grow (Core * c, vector <string> & parameters)
uint16_t ttype = map.tiletypeAt(df::coord(p->pos.x,p->pos.y,p->pos.z));
if(!p->flags.bits.is_shrub && DFHack::tileShape(ttype) == DFHack::SAPLING_OK)
{
p->grow_counter = DFHack::sapling_to_tree_threshold;
p->grow_counter = Vegetation::sapling_to_tree_threshold;
}
}
}

@ -21,10 +21,15 @@ using namespace std;
#include "modules/MapCache.h"
#include "MiscUtils.h"
#include "df/world.h"
using std::vector;
using std::string;
using namespace DFHack;
using namespace DFHack::Simple;
using namespace df::enums;
using df::global::world;
DFhackCExport command_result df_probe (Core * c, vector <string> & parameters);
DFhackCExport command_result df_cprobe (Core * c, vector <string> & parameters);
@ -56,7 +61,6 @@ DFhackCExport command_result df_cprobe (Core * c, vector <string> & parameters)
Console & con = c->con;
CoreSuspender suspend(c);
DFHack::Gui *Gui = c->getGui();
DFHack::Units * cr = c->getUnits();
int32_t cursorX, cursorY, cursorZ;
Gui->getCursorCoords(cursorX,cursorY,cursorZ);
if(cursorX == -30000)
@ -65,11 +69,10 @@ DFhackCExport command_result df_cprobe (Core * c, vector <string> & parameters)
}
else
{
uint32_t ncr;
cr->Start(ncr);
uint32_t ncr = world->units.all.size();
for(auto i = 0; i < ncr; i++)
{
df::unit * unit = cr->GetCreature( i );
df::unit * unit = world->units.all[i];
if(unit->pos.x == cursorX && unit->pos.y == cursorY && unit->pos.z == cursorZ)
{
con.print("Creature %d, race %d (%x), civ %d (%x)\n", unit->id, unit->race, unit->race, unit->civ_id, unit->civ_id);

@ -253,11 +253,6 @@ DFhackCExport command_result prospector (DFHack::Core * c, vector <string> & par
matdata tubeTiles;
uint32_t vegCount = 0;
DFHack::Vegetation *veg = c->getVegetation();
if (showPlants && !veg->Start())
{
con.printerr("Unable to read vegetation; plants won't be listed!\n" );
}
for(uint32_t z = 0; z < z_max; z++)
{
@ -489,10 +484,6 @@ DFhackCExport command_result prospector (DFHack::Core * c, vector <string> & par
}
// Cleanup
if (showPlants)
{
veg->Finish();
}
mats->Finish();
con << std::endl;
return CR_OK;

@ -0,0 +1,278 @@
// Show details of currently active strange mood, if any
#include "Core.h"
#include "Console.h"
#include "Export.h"
#include "PluginManager.h"
#include "modules/Materials.h"
#include "modules/Translation.h"
#include "modules/Items.h"
#include "DataDefs.h"
#include "df/world.h"
#include "df/job.h"
#include "df/job_item.h"
#include "df/general_ref.h"
#include "df/builtin_mats.h"
#include "df/inorganic_raw.h"
#include "df/matter_state.h"
#include "df/unit.h"
#include "df/building.h"
using std::string;
using std::vector;
using namespace DFHack;
using namespace DFHack::Simple;
using namespace df::enums;
using df::global::world;
DFhackCExport command_result df_showmood (Core * c, vector <string> & parameters)
{
if (!parameters.empty())
return CR_WRONG_USAGE;
CoreSuspender suspend(c);
bool found = false;
for (df::job_list_link *cur = world->job_list.next; cur != NULL; cur = cur->next)
{
df::job *job = cur->item;
if ((job->job_type < job_type::StrangeMoodCrafter) || (job->job_type > job_type::StrangeMoodMechanics))
continue;
found = true;
df::unit *unit = NULL;
df::building *building = NULL;
for (int i = 0; i < job->references.size(); i++)
{
df::general_ref *ref = job->references[i];
if (ref->getType() == general_ref_type::UNIT_WORKER)
unit = ref->getUnit();
if (ref->getType() == general_ref_type::BUILDING_HOLDER)
building = ref->getBuilding();
}
if (!unit)
{
c->con.printerr("Found strange mood not attached to any dwarf!\n");
continue;
}
if (unit->mood == mood_type::None)
{
c->con.printerr("Dwarf with strange mood does not have a mood type!\n");
continue;
}
c->con.print("%s %s is currently ", unit->name.first_name.c_str(), Translation::TranslateName(&unit->name, false).c_str());
switch (unit->mood)
{
case mood_type::Macabre:
c->con.print("in a macabre mood");
if (job->job_type != job_type::StrangeMoodBrooding)
c->con.print(" (but isn't actually in a macabre mood?)");
break;
case mood_type::Fell:
c->con.print("in a fell mood");
if (job->job_type != job_type::StrangeMoodFell)
c->con.print(" (but isn't actually in a fell mood?)");
break;
case mood_type::Fey:
case mood_type::Secretive:
case mood_type::Possessed:
switch (unit->mood)
{
case mood_type::Fey:
c->con.print("in a fey mood");
break;
case mood_type::Secretive:
c->con.print("in a secretive mood");
break;
case mood_type::Possessed:
c->con.print("possessed");
break;
}
c->con.print(" with intent to ");
switch (job->job_type)
{
case job_type::StrangeMoodCrafter:
c->con.print("become a Craftsdwarf (or Engraver)");
break;
case job_type::StrangeMoodJeweller:
c->con.print("become a Jeweler");
break;
case job_type::StrangeMoodForge:
c->con.print("become a Metalworker");
break;
case job_type::StrangeMoodMagmaForge:
c->con.print("become a Metalworker using a Magma Forge");
break;
case job_type::StrangeMoodCarpenter:
c->con.print("become a Carpenter");
break;
case job_type::StrangeMoodMason:
c->con.print("become a Mason (or Miner)");
break;
case job_type::StrangeMoodBowyer:
c->con.print("become a Bowyer");
break;
case job_type::StrangeMoodTanner:
c->con.print("become a Leatherworker (or Tanner)");
break;
case job_type::StrangeMoodWeaver:
c->con.print("become a Clothier (or Weaver)");
break;
case job_type::StrangeMoodGlassmaker:
c->con.print("become a Glassmaker");
break;
case job_type::StrangeMoodMechanics:
c->con.print("become a Mechanic");
break;
case job_type::StrangeMoodBrooding:
c->con.print("enter a macabre mood?");
break;
case job_type::StrangeMoodFell:
c->con.print("enter a fell mood?");
break;
}
break;
default:
c->con.print("insane?");
break;
}
if (building)
{
string name;
building->getName(&name);
c->con.print(" and has claimed a %s\n", name.c_str());
}
else
c->con.print(" and has not yet claimed a workshop\n");
for (int i = 0; i < job->job_items.size(); i++)
{
df::job_item *item = job->job_items[i];
c->con.print("Item %i: ", i + 1);
MaterialInfo matinfo(item->mat_type, item->mat_index);
string mat_name = matinfo.toString();
switch (item->item_type)
{
case item_type::BOULDER:
c->con.print("%s boulder", mat_name.c_str());
break;
case item_type::BLOCKS:
c->con.print("%s blocks", mat_name.c_str());
break;
case item_type::WOOD:
c->con.print("%s logs", mat_name.c_str());
break;
case item_type::BAR:
if (matinfo.isInorganicWildcard())
mat_name = "metal";
if (matinfo.inorganic && matinfo.inorganic->flags.is_set(inorganic_flags::WAFERS))
c->con.print("%s wafers", mat_name.c_str());
else
c->con.print("%s bars", mat_name.c_str());
break;
case item_type::SMALLGEM:
c->con.print("%s cut gems", mat_name.c_str());
break;
case item_type::ROUGH:
if (matinfo.isAnyInorganic())
{
if (matinfo.isInorganicWildcard())
mat_name = "any";
c->con.print("%s rough gems", mat_name.c_str());
}
else
c->con.print("raw %s", mat_name.c_str());
break;
case item_type::SKIN_TANNED:
c->con.print("%s leather", mat_name.c_str());
break;
case item_type::CLOTH:
if (matinfo.isNone())
{
if (item->flags2.bits.plant)
mat_name = "any plant fiber";
else if (item->flags2.bits.silk)
mat_name = "any silk";
else if (item->flags2.bits.yarn)
mat_name = "any yarn";
}
c->con.print("%s cloth", mat_name.c_str());
break;
case item_type::REMAINS:
c->con.print("%s remains", mat_name.c_str());
break;
case item_type::CORPSE:
c->con.print("%s %scorpse", mat_name.c_str(), (item->flags1.bits.murdered ? "murdered " : ""));
break;
case item_type::NONE:
if (item->flags2.bits.body_part)
{
if (item->flags2.bits.bone)
c->con.print("%s bones", mat_name.c_str());
else if (item->flags2.bits.shell)
c->con.print("%s shells", mat_name.c_str());
else if (item->flags2.bits.horn)
c->con.print("%s horns", mat_name.c_str());
else if (item->flags2.bits.pearl)
c->con.print("%s pearls", mat_name.c_str());
else if (item->flags2.bits.ivory_tooth)
c->con.print("%s ivory/teeth", mat_name.c_str());
else
c->con.print("%s unknown body parts (%s:%s:%s)",
mat_name.c_str(),
bitfieldToString(item->flags1).c_str(),
bitfieldToString(item->flags2).c_str(),
bitfieldToString(item->flags3).c_str());
}
else
c->con.print("indeterminate %s item (%s:%s:%s)",
mat_name.c_str(),
bitfieldToString(item->flags1).c_str(),
bitfieldToString(item->flags2).c_str(),
bitfieldToString(item->flags3).c_str());
break;
default:
{
ItemTypeInfo itinfo(item->item_type, item->item_subtype);
c->con.print("item %s material %s flags (%s:%s:%s)",
itinfo.toString().c_str(), mat_name.c_str(),
bitfieldToString(item->flags1).c_str(),
bitfieldToString(item->flags2).c_str(),
bitfieldToString(item->flags3).c_str());
break;
}
}
c->con.print(", quantity %i\n", item->quantity);
}
}
if (!found)
c->con.print("No strange moods currently active.\n");
return CR_OK;
}
DFhackCExport const char *plugin_name ( void )
{
return "showmood";
}
DFhackCExport command_result plugin_init (Core *c, std::vector<PluginCommand> &commands)
{
commands.clear();
commands.push_back(PluginCommand("showmood", "Shows items needed for current strange mood.", df_showmood));
return CR_OK;
}
DFhackCExport command_result plugin_shutdown ( Core * c )
{
return CR_OK;
}