diff --git a/docs/changelog.txt b/docs/changelog.txt index 425e570eb..b4447283f 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -56,6 +56,7 @@ Template for new versions: ## New Features - `sort`: search and sort for squad assignment screen - `zone`: advanced unit assignment screens for cages, restraints, and pits/ponds +- `buildingplan`: one-click magma/fire safety filter for planned buildings ## Fixes - Core: reload scripts in mods when a world is unloaded and immediately loaded again diff --git a/library/include/modules/Job.h b/library/include/modules/Job.h index 2a874dc5e..fa10173a0 100644 --- a/library/include/modules/Job.h +++ b/library/include/modules/Job.h @@ -101,8 +101,8 @@ namespace DFHack df::job_item_ref::T_role role, int filter_idx = -1, int insert_idx = -1); - DFHACK_EXPORT bool isSuitableItem(df::job_item *item, df::item_type itype, int isubtype); - DFHACK_EXPORT bool isSuitableMaterial(df::job_item *item, int mat_type, + DFHACK_EXPORT bool isSuitableItem(const df::job_item *item, df::item_type itype, int isubtype); + DFHACK_EXPORT bool isSuitableMaterial(const df::job_item *item, int mat_type, int mat_index, df::item_type itype); DFHACK_EXPORT std::string getName(df::job *job); diff --git a/library/modules/Job.cpp b/library/modules/Job.cpp index 869a6b329..87301fef2 100644 --- a/library/modules/Job.cpp +++ b/library/modules/Job.cpp @@ -567,7 +567,7 @@ bool DFHack::Job::attachJobItem(df::job *job, df::item *item, return true; } -bool Job::isSuitableItem(df::job_item *item, df::item_type itype, int isubtype) +bool Job::isSuitableItem(const df::job_item *item, df::item_type itype, int isubtype) { CHECK_NULL_POINTER(item); @@ -581,7 +581,7 @@ bool Job::isSuitableItem(df::job_item *item, df::item_type itype, int isubtype) } bool Job::isSuitableMaterial( - df::job_item *item, int mat_type, int mat_index, df::item_type itype) + const df::job_item *item, int mat_type, int mat_index, df::item_type itype) { CHECK_NULL_POINTER(item); diff --git a/library/modules/Materials.cpp b/library/modules/Materials.cpp index 7922b5417..1c2d736da 100644 --- a/library/modules/Materials.cpp +++ b/library/modules/Materials.cpp @@ -517,11 +517,13 @@ void MaterialInfo::getMatchBits(df::job_item_flags2 &ok, df::job_item_flags2 &ma TEST(fire_safe, material->heat.melting_point > 11000 && material->heat.boiling_point > 11000 && material->heat.ignite_point > 11000 - && material->heat.heatdam_point > 11000); + && material->heat.heatdam_point > 11000 + && (material->heat.colddam_point == 60001 || material->heat.colddam_point < 11000)); TEST(magma_safe, material->heat.melting_point > 12000 && material->heat.boiling_point > 12000 && material->heat.ignite_point > 12000 - && material->heat.heatdam_point > 12000); + && material->heat.heatdam_point > 12000 + && (material->heat.colddam_point == 60001 || material->heat.colddam_point < 12000)); TEST(deep_material, FLAG(inorganic, inorganic_flags::SPECIAL)); TEST(non_economic, !inorganic || !(plotinfo && vector_get(plotinfo->economic_stone, index))); diff --git a/plugins/buildingplan/buildingplan.cpp b/plugins/buildingplan/buildingplan.cpp index ce424f9c6..540420749 100644 --- a/plugins/buildingplan/buildingplan.cpp +++ b/plugins/buildingplan/buildingplan.cpp @@ -216,9 +216,8 @@ static void load_material_cache() { } static HeatSafety get_heat_safety_filter(const BuildingTypeKey &key) { - // comment out until we can get heat safety working as intended - // if (cur_heat_safety.count(key)) - // return cur_heat_safety.at(key); + if (cur_heat_safety.count(key)) + return cur_heat_safety.at(key); return HEAT_SAFETY_ANY; } @@ -948,22 +947,19 @@ static int getMaterialFilter(lua_State *L) { map counts; scanAvailableItems(*out, type, subtype, custom, index, false, NULL, &counts); HeatSafety heat = get_heat_safety_filter(key); - df::job_item jitem_cur_heat = getJobItemWithHeatSafety( - get_job_items(*out, key)[index], heat); - df::job_item jitem_fire = getJobItemWithHeatSafety( - get_job_items(*out, key)[index], HEAT_SAFETY_FIRE); - df::job_item jitem_magma = getJobItemWithHeatSafety( - get_job_items(*out, key)[index], HEAT_SAFETY_MAGMA); + const df::job_item *jitem = get_job_items(*out, key)[index]; // name -> {count=int, enabled=bool, category=string, heat=string} map> ret; for (auto & entry : mat_cache) { auto &mat = entry.second.first; - if (!mat.matches(jitem_cur_heat)) + if (!mat.matches(jitem)) + continue; + if (!matchesHeatSafety(mat.type, mat.index, heat)) continue; string heat_safety = ""; - if (mat.matches(jitem_magma)) + if (matchesHeatSafety(mat.type, mat.index, HEAT_SAFETY_MAGMA)) heat_safety = "magma-safe"; - else if (mat.matches(jitem_fire)) + else if (matchesHeatSafety(mat.type, mat.index, HEAT_SAFETY_FIRE)) heat_safety = "fire-safe"; auto &name = entry.first; auto &cat = entry.second.second; diff --git a/plugins/buildingplan/buildingplan.h b/plugins/buildingplan/buildingplan.h index 9bfd38731..a17f408a8 100644 --- a/plugins/buildingplan/buildingplan.h +++ b/plugins/buildingplan/buildingplan.h @@ -55,7 +55,7 @@ void set_config_bool(DFHack::PersistentDataItem &c, int index, bool value); std::vector getVectorIds(DFHack::color_ostream &out, const df::job_item *job_item, bool ignore_filters); bool itemPassesScreen(DFHack::color_ostream& out, df::item* item); -df::job_item getJobItemWithHeatSafety(const df::job_item *job_item, HeatSafety heat); +bool matchesHeatSafety(int16_t mat_type, int32_t mat_index, HeatSafety heat); bool matchesFilters(df::item * item, const df::job_item * job_item, HeatSafety heat, const ItemFilter &item_filter, const std::set &special); bool isJobReady(DFHack::color_ostream &out, const std::vector &jitems); void finalizeBuilding(DFHack::color_ostream &out, df::building *bld, bool unsuspend_on_finalize); diff --git a/plugins/buildingplan/buildingplan_cycle.cpp b/plugins/buildingplan/buildingplan_cycle.cpp index f7c23d8ce..c6e0fbc9a 100644 --- a/plugins/buildingplan/buildingplan_cycle.cpp +++ b/plugins/buildingplan/buildingplan_cycle.cpp @@ -66,32 +66,38 @@ bool itemPassesScreen(color_ostream& out, df::item* item) { && isAccessible(out, item); } -df::job_item getJobItemWithHeatSafety(const df::job_item *job_item, HeatSafety heat) { - df::job_item jitem = *job_item; - if (heat >= HEAT_SAFETY_MAGMA) { - jitem.flags2.bits.magma_safe = true; - jitem.flags2.bits.fire_safe = false; - } else if (heat == HEAT_SAFETY_FIRE && !jitem.flags2.bits.magma_safe) - jitem.flags2.bits.fire_safe = true; - return jitem; +bool matchesHeatSafety(int16_t mat_type, int32_t mat_index, HeatSafety heat) { + if (heat == HEAT_SAFETY_ANY) + return true; + + MaterialInfo minfo(mat_type, mat_index); + df::job_item_flags2 ok; + df::job_item_flags2 mask; + minfo.getMatchBits(ok, mask); + + if (heat >= HEAT_SAFETY_MAGMA) + return ok.bits.magma_safe; + if (heat == HEAT_SAFETY_FIRE) + return ok.bits.fire_safe || ok.bits.magma_safe; + return false; } -bool matchesFilters(df::item * item, const df::job_item * job_item, HeatSafety heat, const ItemFilter &item_filter, const std::set &specials) { +bool matchesFilters(df::item * item, const df::job_item * jitem, HeatSafety heat, const ItemFilter &item_filter, const std::set &specials) { // check the properties that are not checked by Job::isSuitableItem() - if (job_item->item_type > -1 && job_item->item_type != item->getType()) + if (jitem->item_type > -1 && jitem->item_type != item->getType()) return false; - if (job_item->item_subtype > -1 && - job_item->item_subtype != item->getSubtype()) + if (jitem->item_subtype > -1 && + jitem->item_subtype != item->getSubtype()) return false; - if (job_item->flags2.bits.building_material && !item->isBuildMat()) + if (jitem->flags2.bits.building_material && !item->isBuildMat()) return false; - if ((job_item->flags1.bits.empty || job_item->flags2.bits.lye_milk_free)) { + if ((jitem->flags1.bits.empty || jitem->flags2.bits.lye_milk_free)) { auto gref = Items::getGeneralRef(item, df::general_ref_type::CONTAINS_ITEM); if (gref) { - if (job_item->flags1.bits.empty) + if (jitem->flags1.bits.empty) return false; if (auto contained_item = gref->getItem(); contained_item) { MaterialInfo mi; @@ -102,23 +108,24 @@ bool matchesFilters(df::item * item, const df::job_item * job_item, HeatSafety h } } - if (job_item->metal_ore > -1 && !item->isMetalOre(job_item->metal_ore)) + if (jitem->metal_ore > -1 && !item->isMetalOre(jitem->metal_ore)) return false; - if (job_item->has_tool_use > df::tool_uses::NONE - && !item->hasToolUse(job_item->has_tool_use)) + if (jitem->has_tool_use > df::tool_uses::NONE + && !item->hasToolUse(jitem->has_tool_use)) return false; if (item->getType() == df::item_type::SLAB && specials.count("engraved") && static_cast(item)->engraving_type != df::slab_engraving_type::Memorial) return false; - df::job_item jitem = getJobItemWithHeatSafety(job_item, heat); + if (!matchesHeatSafety(item->getMaterial(), item->getMaterialIndex(), heat)) + return false; return Job::isSuitableItem( - &jitem, item->getType(), item->getSubtype()) + jitem, item->getType(), item->getSubtype()) && Job::isSuitableMaterial( - &jitem, item->getMaterial(), item->getMaterialIndex(), + jitem, item->getMaterial(), item->getMaterialIndex(), item->getType()) && item_filter.matches(item); } diff --git a/plugins/buildingplan/plannedbuilding.cpp b/plugins/buildingplan/plannedbuilding.cpp index a20d7b29a..b16da01cb 100644 --- a/plugins/buildingplan/plannedbuilding.cpp +++ b/plugins/buildingplan/plannedbuilding.cpp @@ -109,8 +109,7 @@ PlannedBuilding::PlannedBuilding(color_ostream &out, df::building *bld, HeatSafe PlannedBuilding::PlannedBuilding(color_ostream &out, PersistentDataItem &bld_config) : id(get_config_val(bld_config, BLD_CONFIG_ID)), vector_ids(deserialize_vector_ids(out, bld_config)), - //heat_safety((HeatSafety)get_config_val(bld_config, BLD_CONFIG_HEAT)), // until this works - heat_safety(HEAT_SAFETY_ANY), + heat_safety((HeatSafety)get_config_val(bld_config, BLD_CONFIG_HEAT)), item_filters(get_item_filters(out, bld_config)), specials(get_specials(out, bld_config)), bld_config(bld_config) { } diff --git a/plugins/lua/buildingplan/planneroverlay.lua b/plugins/lua/buildingplan/planneroverlay.lua index 643852a6e..9a47b8fed 100644 --- a/plugins/lua/buildingplan/planneroverlay.lua +++ b/plugins/lua/buildingplan/planneroverlay.lua @@ -548,7 +548,6 @@ function PlannerOverlay:init() on_change=function(heat) buildingplan.setHeatSafetyFilter(uibs.building_type, uibs.building_subtype, uibs.custom_type, heat) end, - visible=false, -- until we can make this work the way it's intended }, }, },