Allow setting job item materials.

develop
Alexander Gavrilov 2012-01-05 22:04:05 +04:00
parent 4a59690968
commit 687245abd9
5 changed files with 218 additions and 12 deletions

@ -70,6 +70,24 @@ void print_bits ( T val, DFHack::Console& out )
* Binary search in vectors.
*/
template <typename FT>
int linear_index(const std::vector<FT> &vec, FT key)
{
for (unsigned i = 0; i < vec.size(); i++)
if (vec[i] == key)
return i;
return -1;
}
template <typename FT>
int linear_index(const std::vector<FT*> &vec, const FT &key)
{
for (unsigned i = 0; i < vec.size(); i++)
if (vec[i] && *vec[i] == key)
return i;
return -1;
}
template <typename FT>
int binsearch_index(const std::vector<FT> &vec, FT key, bool exact = true)
{
@ -91,6 +109,15 @@ int binsearch_index(const std::vector<FT> &vec, FT key, bool exact = true)
}
}
template <typename CT, typename FT>
int linear_index(const std::vector<CT*> &vec, FT CT::*field, FT key)
{
for (unsigned i = 0; i < vec.size(); i++)
if (vec[i]->*field == key)
return i;
return -1;
}
template <typename CT, typename FT>
int binsearch_index(const std::vector<CT*> &vec, FT CT::*field, FT key, bool exact = true)
{

@ -48,7 +48,12 @@ namespace df
struct creature_raw;
struct historical_figure;
struct material_vec_ref;
struct job_item;
union job_material_category;
union job_item_flags1;
union job_item_flags2;
union job_item_flags3;
}
namespace DFHack
@ -104,8 +109,16 @@ namespace DFHack
std::string toString(uint16_t temp = 10015, bool named = true);
bool isAnyCloth();
void getMatchBits(df::job_item_flags1 &ok, df::job_item_flags1 &mask);
void getMatchBits(df::job_item_flags2 &ok, df::job_item_flags2 &mask);
void getMatchBits(df::job_item_flags3 &ok, df::job_item_flags3 &mask);
df::craft_material_class getCraftClass();
bool matches(const df::job_material_category &cat);
bool matches(const df::job_item &item);
};
inline bool operator== (const MaterialInfo &a, const MaterialInfo &b) {

@ -43,12 +43,15 @@ using namespace std;
#include "MiscUtils.h"
#include "df/world.h"
#include "df/ui.h"
#include "df/item.h"
#include "df/inorganic_raw.h"
#include "df/plant_raw.h"
#include "df/plant_raw_flags.h"
#include "df/creature_raw.h"
#include "df/historical_figure.h"
#include "df/job_item.h"
#include "df/job_material_category.h"
#include "df/matter_state.h"
#include "df/material_vec_ref.h"
@ -259,6 +262,17 @@ df::craft_material_class MaterialInfo::getCraftClass()
return craft_material_class::None;
}
bool MaterialInfo::isAnyCloth()
{
using namespace df::enums::material_flags;
return material && (
material->flags.is_set(THREAD_PLANT) ||
material->flags.is_set(SILK) ||
material->flags.is_set(YARN)
);
}
bool MaterialInfo::matches(const df::job_material_category &cat)
{
if (!material)
@ -283,6 +297,103 @@ bool MaterialInfo::matches(const df::job_material_category &cat)
return false;
}
bool MaterialInfo::matches(const df::job_item &item)
{
if (!isValid()) return false;
df::job_item_flags1 ok1, mask1;
getMatchBits(ok1, mask1);
df::job_item_flags2 ok2, mask2;
getMatchBits(ok2, mask2);
df::job_item_flags3 ok3, mask3;
getMatchBits(ok3, mask3);
return ((item.flags1.whole & mask1.whole) == (item.flags1.whole & ok1.whole)) &&
((item.flags2.whole & mask2.whole) == (item.flags2.whole & ok2.whole)) &&
((item.flags3.whole & mask3.whole) == (item.flags3.whole & ok3.whole));
}
void MaterialInfo::getMatchBits(df::job_item_flags1 &ok, df::job_item_flags1 &mask)
{
ok.whole = mask.whole = 0;
if (!isValid()) return;
#define MAT_FLAG(name) material->flags.is_set(df::enums::material_flags::name)
#define FLAG(field, name) (field && field->flags.is_set(name))
#define TEST(bit, check) \
mask.bits.bit = true; ok.bits.bit = !!(check);
bool structural = MAT_FLAG(STRUCTURAL_PLANT_MAT);
TEST(millable, structural && FLAG(plant, plant_raw_flags::MILL));
TEST(sharpenable, MAT_FLAG(IS_STONE));
TEST(distillable, structural && FLAG(plant, plant_raw_flags::DRINK));
TEST(processable, structural && FLAG(plant, plant_raw_flags::THREAD));
TEST(bag, isAnyCloth());
TEST(cookable, MAT_FLAG(EDIBLE_COOKED));
TEST(extract_bearing_plant, structural && FLAG(plant, plant_raw_flags::EXTRACT_STILL_VIAL));
TEST(extract_bearing_fish, false);
TEST(extract_bearing_vermin, false);
TEST(processable_to_vial, structural && FLAG(plant, plant_raw_flags::EXTRACT_VIAL));
TEST(processable_to_bag, structural && FLAG(plant, plant_raw_flags::LEAVES));
TEST(processable_to_barrel, structural && FLAG(plant, plant_raw_flags::EXTRACT_BARREL));
TEST(solid, !(MAT_FLAG(ALCOHOL_PLANT) ||
MAT_FLAG(ALCOHOL_CREATURE) ||
MAT_FLAG(LIQUID_MISC_PLANT) ||
MAT_FLAG(LIQUID_MISC_CREATURE) ||
MAT_FLAG(LIQUID_MISC_OTHER)));
TEST(tameable_vermin, false);
TEST(sharpenable, MAT_FLAG(IS_GLASS));
TEST(milk, linear_index(material->reaction_product.id, std::string("CHEESE_MAT")) >= 0);
//04000000 - "milkable" - vtable[107],1,1
}
void MaterialInfo::getMatchBits(df::job_item_flags2 &ok, df::job_item_flags2 &mask)
{
ok.whole = mask.whole = 0;
if (!isValid()) return;
bool is_cloth = isAnyCloth();
TEST(dye, MAT_FLAG(IS_DYE));
TEST(dyeable, is_cloth);
TEST(dyed, is_cloth);
TEST(sewn_imageless, is_cloth);
TEST(glass_making, MAT_FLAG(CRYSTAL_GLASSABLE));
TEST(fire_safe, material->heat.melting_point > 11000);
TEST(magma_safe, material->heat.melting_point > 12000);
TEST(deep_material, FLAG(inorganic, df::enums::inorganic_flags::DEEP_ANY));
TEST(non_economic, inorganic && !(df::global::ui && df::global::ui->economic_stone[index]));
TEST(plant, plant);
TEST(silk, MAT_FLAG(SILK));
TEST(leather, MAT_FLAG(LEATHER));
TEST(bone, MAT_FLAG(BONE));
TEST(shell, MAT_FLAG(SHELL));
TEST(totemable, false);
TEST(horn, MAT_FLAG(HORN));
TEST(pearl, MAT_FLAG(PEARL));
TEST(soap, MAT_FLAG(SOAP));
TEST(ivory_tooth, MAT_FLAG(TOOTH));
//TEST(hair_wool, MAT_FLAG(YARN));
TEST(yarn, MAT_FLAG(YARN));
}
void MaterialInfo::getMatchBits(df::job_item_flags3 &ok, df::job_item_flags3 &mask)
{
ok.whole = mask.whole = 0;
if (!isValid()) return;
TEST(hard, MAT_FLAG(ITEMS_HARD));
}
#undef MAT_FLAG
#undef FLAG
#undef TEST
Module* DFHack::createMaterials()
{
return new Materials();

@ -1 +1 @@
Subproject commit e61e696e2a2bb6b24a86c9c01a26f3133509585e
Subproject commit f20758b0a3ef5aebcbf5896cbb7a824cbdf7b218

@ -60,8 +60,12 @@ DFhackCExport command_result plugin_init (Core *c, std::vector <PluginCommand> &
PluginCommand(
"job", "General job query and manipulation.",
job_cmd, false,
" job query - Print details of the current job.\n"
" job list - Print details of all jobs in the workshop.\n"
" job query\n"
" Print details of the current job.\n"
" job list\n"
" Print details of all jobs in the workshop.\n"
" job item-material <item-idx> <material> [submaterial]\n"
" Replace the exact material id in the job item.\n"
)
);
@ -382,9 +386,9 @@ static command_result job_duplicate(Core * c, vector <string> & parameters)
/* Main job command implementation */
static void print_job_item_details(Core *c, df::job *job, df::job_item *item)
static void print_job_item_details(Core *c, df::job *job, unsigned idx, df::job_item *item)
{
c->con << " Input Item: " << ENUM_KEY_STR(item_type,item->item_type);
c->con << " Input Item " << (idx+1) << ": " << ENUM_KEY_STR(item_type,item->item_type);
if (item->item_subtype != -1)
c->con << " [" << item->item_subtype << "]";
if (item->quantity != 1)
@ -443,7 +447,17 @@ static void print_job_details(Core *c, df::job *job)
c->con << " reaction: " << job->reaction_name << endl;
for (unsigned i = 0; i < job->job_items.size(); i++)
print_job_item_details(c, job, job->job_items[i]);
print_job_item_details(c, job, i, job->job_items[i]);
}
static df::job *getWorkshopJobSafe(Core *c)
{
if (!workshop_job_hotkey(c, c->getTopViewscreen())) {
c->con.printerr("No job is highlighted.\n");
return NULL;
}
return getWorkshopJob(c);
}
static command_result job_cmd(Core * c, vector <string> & parameters)
@ -456,15 +470,11 @@ static command_result job_cmd(Core * c, vector <string> & parameters)
std::string cmd = parameters[0];
if (cmd == "query" || cmd == "list")
{
if (!workshop_job_hotkey(c, c->getTopViewscreen())) {
c->con.printerr("No job is highlighted.\n");
df::job *job = getWorkshopJobSafe(c);
if (!job)
return CR_WRONG_USAGE;
}
if (cmd == "query") {
df::job *job = getWorkshopJob(c);
if (!job)
return CR_FAILURE;
print_job_details(c, job);
} else {
df::building *selected = world->selected_building;
@ -472,6 +482,51 @@ static command_result job_cmd(Core * c, vector <string> & parameters)
print_job_details(c, selected->jobs[i]);
}
}
else if (cmd == "item-material")
{
if (parameters.size() < 1+1+1)
return CR_WRONG_USAGE;
df::job *job = getWorkshopJobSafe(c);
if (!job)
return CR_WRONG_USAGE;
int v = atoi(parameters[1].c_str());
if (v < 1 || v > job->job_items.size()) {
c->con.printerr("Invalid item index.\n");
return CR_WRONG_USAGE;
}
df::job_item *item = job->job_items[v-1];
std::string subtoken = (parameters.size()>3 ? parameters[3] : "");
MaterialInfo info;
if (!info.find(parameters[2], subtoken)) {
c->con.printerr("Could not find the specified material.\n");
return CR_FAILURE;
}
if (!info.matches(*item)) {
c->con.printerr("Material does not match the requirements.\n");
print_job_details(c, job);
return CR_FAILURE;
}
if (job->mat_type != -1 &&
job->mat_type == item->mat_type &&
job->mat_index == item->mat_index)
{
job->mat_type = info.type;
job->mat_index = info.index;
}
item->mat_type = info.type;
item->mat_index = info.index;
c->con << "Job item " << v << " updated." << endl;
print_job_details(c, job);
return CR_OK;
}
else
return CR_WRONG_USAGE;