diff options
| author | Petr Mrázek | 2011-10-30 02:52:25 +0100 |
|---|---|---|
| committer | Petr Mrázek | 2011-10-30 02:52:25 +0100 |
| commit | a3a16295217afea8b7c4c3894e44051441d82095 (patch) | |
| tree | c43e991995f5f51f59b338b5181ab91f2bf21469 /plugins/seedwatch.cpp | |
| parent | 13ca2e608fb478ad1226281a1397091e90e55e20 (diff) | |
| download | dfhack-a3a16295217afea8b7c4c3894e44051441d82095.tar.gz dfhack-a3a16295217afea8b7c4c3894e44051441d82095.tar.bz2 dfhack-a3a16295217afea8b7c4c3894e44051441d82095.tar.xz | |
Fix seedwatch some more.
Diffstat (limited to 'plugins/seedwatch.cpp')
| -rwxr-xr-x | plugins/seedwatch.cpp | 348 |
1 files changed, 91 insertions, 257 deletions
diff --git a/plugins/seedwatch.cpp b/plugins/seedwatch.cpp index 523bbc09..9f8afae0 100755 --- a/plugins/seedwatch.cpp +++ b/plugins/seedwatch.cpp @@ -9,23 +9,20 @@ #include "dfhack/Export.h" #include "dfhack/PluginManager.h" #include "dfhack/Process.h" -#include "dfhack/modules/Items.h" #include "dfhack/modules/Materials.h" +#include "dfhack/modules/Items.h" +#include "dfhack/modules/World.h" +#include "dfhack/modules/kitchen.h" +#include <dfhack/VersionInfo.h> -typedef int32_t t_materialIndex; -typedef int16_t t_material, t_itemType, t_itemSubtype; -typedef int8_t t_exclusionType; +using DFHack::t_materialType; +using DFHack::t_materialIndex; -const unsigned int seedLimit = 400; // a limit on the limits which can be placed on seeds -const t_itemSubtype organicSubtype = -1; // seems to fixed -const t_exclusionType cookingExclusion = 1; // seems to be fixed -const t_itemType limitType = 0; // used to store limit as an entry in the exclusion list. 0 = BAR -const t_itemSubtype limitSubtype = 0; // used to store limit as an entry in the exclusion list -const t_exclusionType limitExclusion = 4; // used to store limit as an entry in the exclusion list const int buffer = 20; // seed number buffer - 20 is reasonable bool running = false; // whether seedwatch is counting the seeds or not -std::map<std::string, std::string> abbreviations; // abbreviations for the standard plants +// abbreviations for the standard plants +std::map<std::string, std::string> abbreviations; bool ignoreSeeds(DFHack::t_itemflags& f) // seeds with the following flags should not be counted { @@ -41,47 +38,26 @@ bool ignoreSeeds(DFHack::t_itemflags& f) // seeds with the following flags shoul f.in_building || f.in_job; }; -void updateCountAndSubindices(DFHack::Core& core, std::map<t_materialIndex, unsigned int>& seedCount, std::map<t_materialIndex, t_material>& seedSubindices, std::map<t_materialIndex, t_material>& plantSubindices) // fills seedCount, seedSubindices and plantSubindices -{ - DFHack::Items& itemsModule = *core.getItems(); - itemsModule.Start(); - std::vector<DFHack::df_item*> items; - itemsModule.readItemVector(items); - - DFHack::df_item * item; - std::size_t size = items.size(); - for(std::size_t i = 0; i < size; ++i) - { - item = items[i]; - t_materialIndex materialIndex = item->getMaterialIndex(); - switch(item->getType()) - { - case DFHack::Items::SEEDS: - seedSubindices[materialIndex] = item->getMaterial(); - if(!ignoreSeeds(item->flags)) ++seedCount[materialIndex]; - break; - case DFHack::Items::PLANT: - plantSubindices[materialIndex] = item->getMaterial(); - break; - } - } - itemsModule.Finish(); -}; void printHelp(DFHack::Core& core) // prints help { core.con.print( - "Watches the numbers of plants and seeds available and enables/disables cooking automatically.\n" + "Watches the numbers of seeds available and enables/disables seed and plant cooking.\n" "Each plant type can be assigned a limit. If their number falls below,\n" "the plants and seeds of that type will be excluded from cookery.\n" - "If the number rises above the limit + %i, then cooking will be allowed.\n" + "If the number rises above the limit + %i, then cooking will be allowed.\n", buffer + ); + core.con.printerr( + "The plugin needs a fortress to be loaded and will deactivate automatically otherwise.\n" + "You have to reactivate with 'seedwatch start' after you load the game.\n" + ); + core.con.print( "Options:\n" "seedwatch all - Adds all plants from the abbreviation list to the watch list.\n" "seedwatch start - Start watching.\n" "seedwatch stop - Stop watching.\n" "seedwatch info - Display whether seedwatch is watching, and the watch list.\n" "seedwatch clear - Clears the watch list.\n\n" - , buffer ); if(!abbreviations.empty()) { @@ -117,209 +93,6 @@ std::string searchAbbreviations(std::string in) } }; -// helps to organise access to the cooking exclusions -class t_kitchenExclusions -{ -public: - t_kitchenExclusions(DFHack::Core& core_) // constructor - : core(core_) - , itemTypes (*((std::vector<t_itemType >*)(addr(core_,0)))) - , itemSubtypes (*((std::vector<t_itemSubtype >*)(addr(core_,1)))) - , materials (*((std::vector<t_material >*)(addr(core_,2)))) - , materialIndices (*((std::vector<t_materialIndex>*)(addr(core_,3)))) - , exclusionTypes (*((std::vector<t_exclusionType>*)(addr(core_,4)))) - { - }; - void print() // print the exclusion list, with the material index also translated into its token (for organics) - for debug really - { - core.con.print("Kitchen Exclusions\n"); - DFHack::Materials& materialsModule= *core.getMaterials(); - materialsModule.ReadOrganicMaterials(); - for(std::size_t i = 0; i < size(); ++i) - { - core.con.print("%2u: IT:%2i IS:%i MI:%2i MS:%3i ET:%i %s\n", i, itemTypes[i], itemSubtypes[i], materialIndices[i], materials[i], exclusionTypes[i], materialsModule.organic[materialIndices[i]].id.c_str()); - } - core.con.print("\n"); - }; - void allowCookery(t_materialIndex materialIndex) // remove this material from the exclusion list if it is in it - { - bool match = false; - do - { - match = false; - std::size_t matchIndex = 0; - for(std::size_t i = 0; i < size(); ++i) - { - if(materialIndices[i] == materialIndex - && (itemTypes[i] == DFHack::Items::SEEDS || itemTypes[i] == DFHack::Items::PLANT) - && exclusionTypes[i] == cookingExclusion - ) - { - match = true; - matchIndex = i; - } - } - if(match) - { - itemTypes.erase(itemTypes.begin() + matchIndex); - itemSubtypes.erase(itemSubtypes.begin() + matchIndex); - materialIndices.erase(materialIndices.begin() + matchIndex); - materials.erase( materials.begin() + matchIndex); - exclusionTypes.erase(exclusionTypes.begin() + matchIndex); - } - } while(match); - }; - - // add this material to the exclusion list, if it is not already in it - void denyCookery(t_materialIndex materialIndex, std::map<t_materialIndex, t_material>& seedMaterials, std::map<t_materialIndex, t_material>& plantMaterials) - { - if( seedMaterials.count(materialIndex) > 0) - { - bool alreadyIn = false; - for(std::size_t i = 0; i < size(); ++i) - { - if(materialIndices[i] == materialIndex - && itemTypes[i] == DFHack::Items::SEEDS - && exclusionTypes[i] == cookingExclusion) - { - alreadyIn = true; - } - } - if(!alreadyIn) - { - itemTypes.push_back(DFHack::Items::SEEDS); - itemSubtypes.push_back(organicSubtype); - materials.push_back( seedMaterials[materialIndex]); - materialIndices.push_back(materialIndex); - exclusionTypes.push_back(cookingExclusion); - } - } - if( plantMaterials.count(materialIndex) > 0) - { - bool alreadyIn = false; - for(std::size_t i = 0; i < size(); ++i) - { - if(materialIndices[i] == materialIndex - && itemTypes[i] == DFHack::Items::PLANT - && exclusionTypes[i] == cookingExclusion) - { - alreadyIn = true; - } - } - if(!alreadyIn) - { - itemTypes.push_back(DFHack::Items::PLANT); - itemSubtypes.push_back(organicSubtype); - materials.push_back(plantMaterials[materialIndex]); - materialIndices.push_back(materialIndex); - exclusionTypes.push_back(cookingExclusion); - } - } - }; - - // fills a map with info from the limit info storage entries in the exclusion list - void fillWatchMap(std::map<t_materialIndex, unsigned int>& watchMap) - { - watchMap.clear(); - for(std::size_t i = 0; i < size(); ++i) - { - if(itemTypes[i] == limitType && itemSubtypes[i] == limitSubtype && exclusionTypes[i] == limitExclusion) - { - watchMap[materialIndices[i]] = (unsigned int) materials[i]; - } - } - }; - - // removes a limit info storage entry from the exclusion list if it is in it - void removeLimit(t_materialIndex materialIndex) - { - bool match = false; - do - { - match = false; - std::size_t matchIndex = 0; - for(std::size_t i = 0; i < size(); ++i) - { - if(itemTypes[i] == limitType - && itemSubtypes[i] == limitSubtype - && materialIndices[i] == materialIndex - && exclusionTypes[i] == limitExclusion) - { - match = true; - matchIndex = i; - } - } - if(match) - { - itemTypes.erase(itemTypes.begin() + matchIndex); - itemSubtypes.erase(itemSubtypes.begin() + matchIndex); - materials.erase(materials.begin() + matchIndex); - materialIndices.erase(materialIndices.begin() + matchIndex); - exclusionTypes.erase(exclusionTypes.begin() + matchIndex); - } - } while(match); - }; - // add a limit info storage item to the exclusion list, or alters an existing one - void setLimit(t_materialIndex materialIndex, unsigned int limit) - { - removeLimit(materialIndex); - if(limit > seedLimit) limit = seedLimit; - - itemTypes.push_back(limitType); - itemSubtypes.push_back(limitSubtype); - materialIndices.push_back(materialIndex); - materials.push_back((t_material) (limit < seedLimit) ? limit : seedLimit); - exclusionTypes.push_back(limitExclusion); - }; - void clearLimits() // clears all limit info storage items from the exclusion list - { - bool match = false; - do - { - match = false; - std::size_t matchIndex; - for(std::size_t i = 0; i < size(); ++i) - { - if(itemTypes[i] == limitType - && itemSubtypes[i] == limitSubtype - && exclusionTypes[i] == limitExclusion) - { - match = true; - matchIndex = i; - } - } - if(match) - { - itemTypes.erase(itemTypes.begin() + matchIndex); - itemSubtypes.erase(itemSubtypes.begin() + matchIndex); - materialIndices.erase(materialIndices.begin() + matchIndex); - materials.erase( materials.begin() + matchIndex); - exclusionTypes.erase(exclusionTypes.begin() + matchIndex); - } - } while(match); - }; -private: - DFHack::Core& core; - std::vector<t_itemType>& itemTypes; // the item types vector of the kitchen exclusion list - std::vector<t_itemSubtype>& itemSubtypes; // the item subtype vector of the kitchen exclusion list - std::vector<t_material>& materials; // the material subindex vector of the kitchen exclusion list - std::vector<t_materialIndex>& materialIndices; // the material index vector of the kitchen exclusion list - std::vector<t_exclusionType>& exclusionTypes; // the exclusion type vector of the kitchen excluions list - std::size_t size() // the size of the exclusions vectors (they are all the same size - if not, there is a problem!) - { - return itemTypes.size(); - }; - //FIXME: ugly, ugly hack. Use memory.xml instead. - static uint32_t addr(const DFHack::Core& core, int index) - { - #ifdef LINUX_BUILD - return 0x93f2b00 + 0xC * index; - #else - return core.p->getBase() + 0x014F0BB4 - 0x400000 + 0x10 * index; - #endif - }; -}; - DFhackCExport DFHack::command_result df_seedwatch(DFHack::Core* pCore, std::vector<std::string>& parameters) { DFHack::Core& core = *pCore; @@ -339,6 +112,19 @@ DFhackCExport DFHack::command_result df_seedwatch(DFHack::Core* pCore, std::vect materialsReverser[organics[i].id] = i; } + DFHack::World *w = core.getWorld(); + DFHack::t_gamemodes gm; + w->ReadGameMode(gm);// FIXME: check return value + + // if game mode isn't fortress mode + if(gm.g_mode != DFHack::GAMEMODE_DWARF || gm.g_type != DFHack::GAMETYPE_DWARF_MAIN) + { + // just print the help + printHelp(core); + core.Resume(); + return DFHack::CR_OK; + } + std::string par; int limit; switch(parameters.size()) @@ -362,7 +148,7 @@ DFhackCExport DFHack::command_result df_seedwatch(DFHack::Core* pCore, std::vect } else if(par == "clear") { - t_kitchenExclusions kitchenExclusions(core); + DFHack::Kitchen::Exclusions kitchenExclusions(core); kitchenExclusions.clearLimits(); core.con.print("seedwatch watchlist cleared\n"); } @@ -377,7 +163,7 @@ DFhackCExport DFHack::command_result df_seedwatch(DFHack::Core* pCore, std::vect { core.con.print("seedwatch is not supervising. Use 'seedwatch start' to start supervision.\n"); } - t_kitchenExclusions kitchenExclusions(core); + DFHack::Kitchen::Exclusions kitchenExclusions(core); std::map<t_materialIndex, unsigned int> watchMap; kitchenExclusions.fillWatchMap(watchMap); if(watchMap.empty()) @@ -395,17 +181,35 @@ DFhackCExport DFHack::command_result df_seedwatch(DFHack::Core* pCore, std::vect } else if(par == "debug") { - t_kitchenExclusions kitchenExclusions(core); + DFHack::Kitchen::Exclusions kitchenExclusions(core); std::map<t_materialIndex, unsigned int> watchMap; kitchenExclusions.fillWatchMap(watchMap); - kitchenExclusions.print(); + kitchenExclusions.debug_print(); + } + /* + else if(par == "dumpmaps") + { + + core.con.print("Plants:\n"); + for(auto i = plantMaterialTypes.begin(); i != plantMaterialTypes.end(); i++) + { + auto t = materialsModule.df_organic->at(i->first); + core.con.print("%s : %u %u\n", organics[i->first].id.c_str(), i->second, t->material_basic_mat); + } + core.con.print("Seeds:\n"); + for(auto i = seedMaterialTypes.begin(); i != seedMaterialTypes.end(); i++) + { + auto t = materialsModule.df_organic->at(i->first); + core.con.print("%s : %u %u\n", organics[i->first].id.c_str(), i->second, t->material_seed); + } } + */ else { std::string token = searchAbbreviations(par); if(materialsReverser.count(token) > 0) { - t_kitchenExclusions kitchenExclusions(core); + DFHack::Kitchen::Exclusions kitchenExclusions(core); kitchenExclusions.removeLimit(materialsReverser[token]); core.con.print("%s is not being watched\n", token.c_str()); } @@ -422,7 +226,7 @@ DFhackCExport DFHack::command_result df_seedwatch(DFHack::Core* pCore, std::vect { for(std::map<std::string, std::string>::const_iterator i = abbreviations.begin(); i != abbreviations.end(); ++i) { - t_kitchenExclusions kitchenExclusions(core); + DFHack::Kitchen::Exclusions kitchenExclusions(core); if(materialsReverser.count(i->second) > 0) kitchenExclusions.setLimit(materialsReverser[i->second], limit); } } @@ -431,7 +235,7 @@ DFhackCExport DFHack::command_result df_seedwatch(DFHack::Core* pCore, std::vect std::string token = searchAbbreviations(parameters[0]); if(materialsReverser.count(token) > 0) { - t_kitchenExclusions kitchenExclusions(core); + DFHack::Kitchen::Exclusions kitchenExclusions(core); kitchenExclusions.setLimit(materialsReverser[token], limit); core.con.print("%s is being watched.\n", token.c_str()); } @@ -489,22 +293,52 @@ DFhackCExport DFHack::command_result plugin_onupdate(DFHack::Core* pCore) if(running) { DFHack::Core& core = *pCore; + DFHack::World *w = core.getWorld(); + DFHack::t_gamemodes gm; + w->ReadGameMode(gm);// FIXME: check return value + // if game mode isn't fortress mode + if(gm.g_mode != DFHack::GAMEMODE_DWARF || gm.g_type != DFHack::GAMETYPE_DWARF_MAIN) + { + // stop running. + running = false; + core.con.printerr("seedwatch deactivated due to game mode switch\n"); + return DFHack::CR_OK; + } + // this is dwarf mode, continue std::map<t_materialIndex, unsigned int> seedCount; // the number of seeds - std::map<t_materialIndex, t_material> seedSubindices; // holds information needed to add entries to the cooking exclusions - std::map<t_materialIndex, t_material> plantSubindices; // holds information need to add entries to the cooking exclusions - updateCountAndSubindices(core, seedCount, seedSubindices, plantSubindices); - t_kitchenExclusions kitchenExclusions(core); + DFHack::Items& itemsModule = *core.getItems(); + itemsModule.Start(); + std::vector<DFHack::df_item*> items; + itemsModule.readItemVector(items); + DFHack::df_item * item; + // count all seeds and plants by RAW material + for(std::size_t i = 0; i < items.size(); ++i) + { + item = items[i]; + t_materialIndex materialIndex = item->getMaterialIndex(); + switch(item->getType()) + { + case DFHack::Items::SEEDS: + if(!ignoreSeeds(item->flags)) ++seedCount[materialIndex]; + break; + case DFHack::Items::PLANT: + break; + } + } + itemsModule.Finish(); + + DFHack::Kitchen::Exclusions kitchenExclusions(core); std::map<t_materialIndex, unsigned int> watchMap; kitchenExclusions.fillWatchMap(watchMap); - for(std::map<t_materialIndex, unsigned int>::const_iterator i = watchMap.begin(); i != watchMap.end(); ++i) + for(auto i = watchMap.begin(); i != watchMap.end(); ++i) { if(seedCount[i->first] <= i->second) { - kitchenExclusions.denyCookery(i->first, seedSubindices, plantSubindices); + kitchenExclusions.denyPlantSeedCookery(i->first); } else if(i->second + buffer < seedCount[i->first]) { - kitchenExclusions.allowCookery(i->first); + kitchenExclusions.allowPlantSeedCookery(i->first); } } } |
