#include "OrganicMatLookup.h" #include "StockpileUtils.h" #include "Debug.h" #include "df/creature_raw.h" #include "df/caste_raw.h" #include "df/world.h" using namespace DFHack; using namespace df::enums; using df::global::world; namespace DFHack { DBG_EXTERN(stockpiles, log); } /** * Helper class for mapping the various organic mats between their material indices * and their index in the stockpile_settings structures. */ void OrganicMatLookup::food_mat_by_idx(color_ostream& out, organic_mat_category::organic_mat_category mat_category, std::vector::size_type food_idx, FoodMat& food_mat) { DEBUG(log, out).print("food_lookup: food_idx(%zd)\n", food_idx); df::world_raws& raws = world->raws; df::special_mat_table table = raws.mat_table; int32_t main_idx = table.organic_indexes[mat_category][food_idx]; int16_t type = table.organic_types[mat_category][food_idx]; if (mat_category == organic_mat_category::Fish || mat_category == organic_mat_category::UnpreparedFish || mat_category == organic_mat_category::Eggs) { food_mat.creature = raws.creatures.all[type]; food_mat.caste = food_mat.creature->caste[main_idx]; DEBUG(log, out).print("special creature type(%d) caste(%d)\n", type, main_idx); } else { food_mat.material.decode(type, main_idx); DEBUG(log, out).print("type(%d) index(%d) token(%s)\n", type, main_idx, food_mat.material.getToken().c_str()); } } std::string OrganicMatLookup::food_token_by_idx(color_ostream& out, organic_mat_category::organic_mat_category mat_category, std::vector::size_type idx) { FoodMat food_mat; food_mat_by_idx(out, mat_category, idx, food_mat); if (food_mat.material.isValid()) { return food_mat.material.getToken(); } else if (food_mat.creature) { return food_mat.creature->creature_id + ":" + food_mat.caste->caste_id; } return std::string(); } size_t OrganicMatLookup::food_max_size(organic_mat_category::organic_mat_category mat_category) { return world->raws.mat_table.organic_types[mat_category].size(); } void OrganicMatLookup::food_build_map() { if (index_built) return; df::world_raws& raws = world->raws; df::special_mat_table table = raws.mat_table; using df::enums::organic_mat_category::organic_mat_category; using traits = df::enum_traits; for (int32_t mat_category = traits::first_item_value; mat_category <= traits::last_item_value; ++mat_category) { for (size_t i = 0; i < table.organic_indexes[mat_category].size(); ++i) { int16_t type = table.organic_types[mat_category].at(i); int32_t index = table.organic_indexes[mat_category].at(i); food_index[mat_category].insert(std::make_pair(std::make_pair(type, index), i)); // wtf.. only in c++ } } index_built = true; } int16_t OrganicMatLookup::food_idx_by_token(color_ostream& out, organic_mat_category::organic_mat_category mat_category, const std::string& token) { df::world_raws& raws = world->raws; df::special_mat_table table = raws.mat_table; DEBUG(log, out).print("food_idx_by_token:\n"); if (mat_category == organic_mat_category::Fish || mat_category == organic_mat_category::UnpreparedFish || mat_category == organic_mat_category::Eggs) { std::vector tokens; split_string(&tokens, token, ":"); if (tokens.size() != 2) { WARN(log, out).print("creature invalid CREATURE:CASTE token: %s\n", token.c_str()); return -1; } int16_t creature_idx = find_creature(tokens[0]); if (creature_idx < 0) { WARN(log, out).print("creature invalid token %s\n", tokens[0].c_str()); return -1; } int16_t food_idx = linear_index(table.organic_types[mat_category], creature_idx); if (tokens[1] == "MALE") food_idx += 1; if (table.organic_types[mat_category][food_idx] == creature_idx) { DEBUG(log, out).print("creature %s caste %s creature_idx(%d) food_idx(%d)\n", token.c_str(), tokens[1].c_str(), creature_idx, food_idx); return food_idx; } WARN(log, out).print("creature caste not found: %s caste %s creature_idx(%d) food_idx(%d)\n", token.c_str(), tokens[1].c_str(), creature_idx, food_idx); return -1; } if (!index_built) food_build_map(); MaterialInfo mat_info = food_mat_by_token(token); int16_t type = mat_info.type; int32_t index = mat_info.index; auto it = food_index[mat_category].find(std::make_pair(type, index)); if (it != food_index[mat_category].end()) { DEBUG(log, out).print("matinfo: %s type(%d) idx(%d) food_idx(%zd)\n", token.c_str(), mat_info.type, mat_info.index, it->second); return it->second; } WARN(log, out).print("matinfo: %s type(%d) idx(%d) food_idx not found :(\n", token.c_str(), mat_info.type, mat_info.index); return -1; } MaterialInfo OrganicMatLookup::food_mat_by_token(const std::string& token) { MaterialInfo mat_info; mat_info.find(token); return mat_info; } bool OrganicMatLookup::index_built = false; std::vector OrganicMatLookup::food_index = std::vector(df::enum_traits< df::organic_mat_category >::last_item_value + 1);