Пример #1
0
static void push_matinfo(lua_State *state, MaterialInfo &info)
{
    if (!info.isValid())
    {
        lua_pushnil(state);
        return;
    }

    lua_newtable(state);
    lua_pushvalue(state, lua_upvalueindex(1));
    lua_setmetatable(state, -2);

    lua_pushinteger(state, info.type);
    lua_setfield(state, -2, "type");
    lua_pushinteger(state, info.index);
    lua_setfield(state, -2, "index");

#define SETOBJ(name) { \
    Lua::PushDFObject(state, info.name); \
    lua_setfield(state, -2, #name); \
}
    SETOBJ(material);
    if (info.plant) SETOBJ(plant);
    if (info.creature) SETOBJ(creature);
    if (info.inorganic) SETOBJ(inorganic);
    if (info.figure) SETOBJ(figure);
#undef SETOBJ

    if (info.mode != MaterialInfo::Builtin)
    {
        lua_pushinteger(state, info.subtype);
        lua_setfield(state, -2, "subtype");
    }

    const char *id = "builtin";
    switch (info.mode)
    {
        case MaterialInfo::Plant: id = "plant"; break;
        case MaterialInfo::Creature: id = "creature"; break;
        case MaterialInfo::Inorganic: id = "inorganic"; break;
        default: break;
    }

    lua_pushstring(state, id);
    lua_setfield(state, -2, "mode");
}
Пример #2
0
static std::string shortJobDescription(df::job *job)
{
    std::string rv = stl_sprintf("job %d: ", job->id);

    if (job->job_type != job_type::CustomReaction)
        rv += ENUM_KEY_STR(job_type, job->job_type);
    else
        rv += job->reaction_name;

    MaterialInfo mat;
    df::dfhack_material_category mat_mask;
    guess_job_material(job, mat, mat_mask);

    if (mat.isValid())
        rv += " [" + mat.toString() + "]";
    else if (mat_mask.whole)
        rv += " [" + bitfield_to_string(mat_mask) + "]";

    return rv;
}
Пример #3
0
static void guess_job_material(df::job *job, MaterialInfo &mat, df::dfhack_material_category &mat_mask)
{
    using namespace df::enums::job_type;

    if (job->job_type == PrepareMeal)
        mat.decode(-1);
    else
        mat.decode(job);

    mat_mask.whole = job->material_category.whole;

    // Material from the job enum
    const char *job_material = ENUM_ATTR(job_type, material, job->job_type);
    if (job_material)
    {
        MaterialInfo info;
        if (info.findBuiltin(job_material))
            mat = info;
        else
            parseJobMaterialCategory(&mat_mask, job_material);
    }

    // Material from the job reagent
    if (!mat.isValid() && !job->job_items.empty() &&
        (job->job_items.size() == 1 ||
         job->job_items[0]->item_type == item_type::PLANT))
    {
        mat.decode(job->job_items[0]);

        switch (job->job_items[0]->item_type)
        {
        case item_type::WOOD:
            mat_mask.bits.wood = mat_mask.bits.wood2 = true;
            break;

        default:
            break;
        }
    }
}
Пример #4
0
void DFHack::describeMaterial(BasicMaterialInfo *info, const MaterialInfo &mat,
                              const BasicMaterialInfoMask *mask)
{
    assert(mat.isValid());

    info->set_type(mat.type);
    info->set_index(mat.index);

    describeMaterial(info, mat.material, mask);

    switch (mat.mode) {
    case MaterialInfo::Inorganic:
        info->set_token(mat.inorganic->id);
        if (mask && mask->flags())
            flagarray_to_ints(info->mutable_inorganic_flags(), mat.inorganic->flags);
        break;

    case MaterialInfo::Creature:
        info->set_subtype(mat.subtype);
        if (mat.figure)
        {
            info->set_histfig_id(mat.index);
            info->set_creature_id(mat.figure->race);
        }
        else
            info->set_creature_id(mat.index);
        break;

    case MaterialInfo::Plant:
        info->set_plant_id(mat.index);
        break;

    default:
        break;
    }
}
Пример #5
0
static ItemConstraint *get_constraint(color_ostream &out, const std::string &str, PersistentDataItem *cfg)
{
    std::vector<std::string> tokens;
    split_string(&tokens, str, "/");

    if (tokens.size() > 4)
        return NULL;

    int weight = 0;

    bool is_craft = false;
    ItemTypeInfo item;

    if (tokens[0] == "ANY_CRAFT" || tokens[0] == "CRAFTS") {
        is_craft = true;
    } else if (!item.find(tokens[0]) || !item.isValid()) {
        out.printerr("Cannot find item type: %s\n", tokens[0].c_str());
        return NULL;
    }

    if (item.subtype >= 0)
        weight += 10000;

    df::dfhack_material_category mat_mask;
    std::string maskstr = vector_get(tokens,1);
    if (!maskstr.empty() && !parseJobMaterialCategory(&mat_mask, maskstr)) {
        out.printerr("Cannot decode material mask: %s\n", maskstr.c_str());
        return NULL;
    }
    
    if (mat_mask.whole != 0)
        weight += 100;
    
    MaterialInfo material;
    std::string matstr = vector_get(tokens,2);
    if (!matstr.empty() && (!material.find(matstr) || !material.isValid())) {
        out.printerr("Cannot find material: %s\n", matstr.c_str());
        return NULL;
    }

    item_quality::item_quality minqual = item_quality::Ordinary;
    std::string qualstr = vector_get(tokens, 3);
    if(!qualstr.empty()) {
	    if(qualstr == "ordinary") minqual = item_quality::Ordinary;
	    else if(qualstr == "wellcrafted") minqual = item_quality::WellCrafted;
	    else if(qualstr == "finelycrafted") minqual = item_quality::FinelyCrafted;
	    else if(qualstr == "superior") minqual = item_quality::Superior;
	    else if(qualstr == "exceptional") minqual = item_quality::Exceptional;
	    else if(qualstr == "masterful") minqual = item_quality::Masterful;
	    else {
		    out.printerr("Cannot find quality: %s\nKnown qualities: ordinary, wellcrafted, finelycrafted, superior, exceptional, masterful\n", qualstr.c_str());
		    return NULL;
	    }
    }

    if (material.type >= 0)
        weight += (material.index >= 0 ? 5000 : 1000);

    if (mat_mask.whole && material.isValid() && !material.matches(mat_mask)) {
        out.printerr("Material %s doesn't match mask %s\n", matstr.c_str(), maskstr.c_str());
        return NULL;
    }

    for (size_t i = 0; i < constraints.size(); i++)
    {
        ItemConstraint *ct = constraints[i];
        if (ct->is_craft == is_craft &&
            ct->item == item && ct->material == material &&
            ct->mat_mask.whole == mat_mask.whole &&
	    ct->min_quality == minqual)
            return ct;
    }

    ItemConstraint *nct = new ItemConstraint;
    nct->is_craft = is_craft;
    nct->item = item;
    nct->material = material;
    nct->mat_mask = mat_mask;
    nct->min_quality = minqual;
    nct->weight = weight;

    if (cfg)
        nct->config = *cfg;
    else
    {
        nct->config = Core::getInstance().getWorld()->AddPersistentData("workflow/constraints");
        nct->init(str);
    }

    constraints.push_back(nct);
    return nct;
}
Пример #6
0
static ItemConstraint *get_constraint(Core *c, const std::string &str, PersistentDataItem *cfg)
{
    std::vector<std::string> tokens;
    split_string(&tokens, str, "/");

    if (tokens.size() > 3)
        return NULL;

    int weight = 0;

    ItemTypeInfo item;
    if (!item.find(tokens[0]) || !item.isValid()) {
        c->con.printerr("Cannot find item type: %s\n", tokens[0].c_str());
        return NULL;
    }

    if (item.subtype >= 0)
        weight += 10000;

    df::dfhack_material_category mat_mask;
    std::string maskstr = vector_get(tokens,1);
    if (!maskstr.empty() && !parseJobMaterialCategory(&mat_mask, maskstr)) {
        c->con.printerr("Cannot decode material mask: %s\n", maskstr.c_str());
        return NULL;
    }

    if (mat_mask.whole != 0)
        weight += 100;

    MaterialInfo material;
    std::string matstr = vector_get(tokens,2);
    if (!matstr.empty() && (!material.find(matstr) || !material.isValid())) {
        c->con.printerr("Cannot find material: %s\n", matstr.c_str());
        return NULL;
    }

    if (material.type >= 0)
        weight += (material.index >= 0 ? 5000 : 1000);

    if (mat_mask.whole && material.isValid() && !material.matches(mat_mask)) {
        c->con.printerr("Material %s doesn't match mask %s\n", matstr.c_str(), maskstr.c_str());
        return NULL;
    }

    for (size_t i = 0; i < constraints.size(); i++)
    {
        ItemConstraint *ct = constraints[i];
        if (ct->item == item && ct->material == material &&
            ct->mat_mask.whole == mat_mask.whole)
            return ct;
    }

    ItemConstraint *nct = new ItemConstraint;
    nct->item = item;
    nct->material = material;
    nct->mat_mask = mat_mask;
    nct->weight = weight;

    if (cfg)
        nct->config = *cfg;
    else
    {
        nct->config = c->getWorld()->AddPersistentData("workflow/constraints");
        nct->init(str);
    }

    constraints.push_back(nct);
    return nct;
}
Пример #7
0
static command_result job_cmd(Core * c, vector <string> & parameters)
{
    CoreSuspender suspend(c);

    std::string cmd = (parameters.empty() ? "query" : parameters[0]);
    if (cmd == "query" || cmd == "list")
    {
        df::job *job = getSelectedJob(c);
        if (!job)
            return CR_WRONG_USAGE;

        if (cmd == "query") {
            printJobDetails(c, job);
        } else {
            if (!workshop_job_hotkey(c, c->getTopViewscreen()))
                return CR_WRONG_USAGE;

            df::building *selected = world->selected_building;
            for (size_t i = 0; i < selected->jobs.size(); i++)
                printJobDetails(c, selected->jobs[i]);
        }
    }
    else if (cmd == "item-material")
    {
        if (parameters.size() != 3)
            return CR_WRONG_USAGE;

        df::job *job = getSelectedJob(c);
        df::job_item *item = getJobItem(c, job, parameters[1]);
        if (!item)
            return CR_WRONG_USAGE;

        ItemTypeInfo iinfo(item);
        MaterialInfo minfo;

        if (!minfo.find(parameters[2])) {
            c->con.printerr("Could not find the specified material.\n");
            return CR_FAILURE;
        }

        if (minfo.isValid() && !iinfo.matches(*item, &minfo)) {
            c->con.printerr("Material does not match the requirements.\n");
            printJobDetails(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 = minfo.type;
            job->mat_index = minfo.index;
        }

        item->mat_type = minfo.type;
        item->mat_index = minfo.index;

        c->con << "Job item updated." << endl;

        if (item->item_type < 0 && minfo.isValid())
            c->con.printerr("WARNING: Due to a probable bug, creature & plant material subtype\n"
                            "         is ignored unless the item type is also specified.\n");

        printJobDetails(c, job);
        return CR_OK;
    }
    else if (cmd == "item-type")
    {
        if (parameters.size() != 3)
            return CR_WRONG_USAGE;

        df::job *job = getSelectedJob(c);
        df::job_item *item = getJobItem(c, job, parameters[1]);
        if (!item)
            return CR_WRONG_USAGE;

        ItemTypeInfo iinfo;
        MaterialInfo minfo(item);

        if (!iinfo.find(parameters[2])) {
            c->con.printerr("Could not find the specified item type.\n");
            return CR_FAILURE;
        }

        if (iinfo.isValid() && !iinfo.matches(*item, &minfo)) {
            c->con.printerr("Item type does not match the requirements.\n");
            printJobDetails(c, job);
            return CR_FAILURE;
        }

        item->item_type = iinfo.type;
        item->item_subtype = iinfo.subtype;

        c->con << "Job item updated." << endl;
        printJobDetails(c, job);
        return CR_OK;
    }
    else
        return CR_WRONG_USAGE;

    return CR_OK;
}
Пример #8
0
static command_result job_material_in_job(Core *c, MaterialInfo &new_mat)
{
    df::job *job = getSelectedWorkshopJob(c);
    if (!job)
        return CR_FAILURE;

    if (!new_mat.isValid() || new_mat.type != 0)
    {
        c->con.printerr("New job material isn't inorganic: %s\n",
                        new_mat.toString().c_str());
        return CR_FAILURE;
    }

    MaterialInfo cur_mat(job);

    if (!cur_mat.isValid() || cur_mat.type != 0)
    {
        c->con.printerr("Current job material isn't inorganic: %s\n",
                        cur_mat.toString().c_str());
        return CR_FAILURE;
    }

    df::craft_material_class old_class = cur_mat.getCraftClass();
    if (old_class == craft_material_class::None)
    {
        c->con.printerr("Unexpected current material type: %s\n",
                        cur_mat.toString().c_str());
        return CR_FAILURE;
    }
    if (new_mat.getCraftClass() != old_class)
    {
        c->con.printerr("New material %s does not satisfy requirement: %s\n",
                        new_mat.toString().c_str(), ENUM_KEY_STR(craft_material_class, old_class));
        return CR_FAILURE;
    }

    for (size_t i = 0; i < job->job_items.size(); i++)
    {
        df::job_item *item = job->job_items[i];
        MaterialInfo item_mat(item);

        if (item_mat != cur_mat)
        {
            c->con.printerr("Job item %d has different material: %s\n",
                            i, item_mat.toString().c_str());
            return CR_FAILURE;
        }

        if (!new_mat.matches(*item))
        {
            c->con.printerr("Job item %d requirements not satisfied by %s.\n",
                            i, new_mat.toString().c_str());
            return CR_FAILURE;
        }
    }

    // Apply the substitution
    job->mat_type = new_mat.type;
    job->mat_index = new_mat.index;

    for (size_t i = 0; i < job->job_items.size(); i++)
    {
        df::job_item *item = job->job_items[i];
        item->mat_type = new_mat.type;
        item->mat_index = new_mat.index;
    }

    c->con << "Applied material '" << new_mat.toString()
           << "' to job " << ENUM_KEY_STR(job_type,job->job_type) << endl;
    return CR_OK;
}