From f55030909f83c54b5b74d085d0dd1253b60e210e Mon Sep 17 00:00:00 2001 From: Quietust Date: Wed, 27 Feb 2013 11:09:06 -0600 Subject: [PATCH] Add createItem plugin, spawns an item at the selected unit's feet --- plugins/CMakeLists.txt | 1 + plugins/createitem.cpp | 234 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 235 insertions(+) create mode 100644 plugins/createitem.cpp diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index f2bf4d4a4..65a550018 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -136,6 +136,7 @@ if (BUILD_SUPPORTED) DFHACK_PLUGIN(autoSyndrome autoSyndrome.cpp) DFHACK_PLUGIN(trueTransformation trueTransformation.cpp) DFHACK_PLUGIN(infiniteSky infiniteSky.cpp) + DFHACK_PLUGIN(createitem createitem.cpp) endif() diff --git a/plugins/createitem.cpp b/plugins/createitem.cpp new file mode 100644 index 000000000..722932a99 --- /dev/null +++ b/plugins/createitem.cpp @@ -0,0 +1,234 @@ +// Create arbitrary items + +#include "Core.h" +#include "Console.h" +#include "Export.h" +#include "PluginManager.h" +#include "MiscUtils.h" + +#include "modules/Maps.h" +#include "modules/Gui.h" +#include "modules/Items.h" +#include "modules/Materials.h" + +#include "DataDefs.h" +#include "df/world.h" +#include "df/ui.h" +#include "df/unit.h" +#include "df/historical_entity.h" +#include "df/world_site.h" +#include "df/item.h" +#include "df/creature_raw.h" +#include "df/caste_raw.h" +#include "df/reaction_reagent.h" +#include "df/reaction_product_itemst.h" + +using namespace std; +using namespace DFHack; + +using df::global::world; +using df::global::ui; + +DFHACK_PLUGIN("createitem"); + +command_result df_createitem (color_ostream &out, vector & parameters); + +DFhackCExport command_result plugin_init (color_ostream &out, std::vector &commands) +{ + commands.push_back(PluginCommand("createitem", "Create arbitrary item at the selected unit's feet.", df_createitem)); + return CR_OK; +} + +DFhackCExport command_result plugin_shutdown ( color_ostream &out ) +{ + return CR_OK; +} + +bool makeItem (df::reaction_product_itemst *prod, df::unit *unit, int hand = 0) +{ + vector out_items; + vector in_reag; + vector in_items; + + prod->produce(unit, &out_items, &in_reag, &in_items, 1, df::job_skill::NONE, ui->main.fortress_entity, df::world_site::find(ui->site_id)); + if (!out_items.size()) + return false; + for (size_t i = 0; i < out_items.size(); i++) + { + out_items[i]->moveToGround(unit->pos.x, unit->pos.y, unit->pos.z); + if (hand) + out_items[i]->setGloveHandedness(hand); + } + return true; +} + +command_result df_createitem (color_ostream &out, vector & parameters) +{ + string item_str, material_str; + df::item_type item_type; + int16_t item_subtype; + int16_t mat_type; + int32_t mat_index; + + if (parameters.size() != 2) + { + out.print("Syntax: createitem ITEM_TYPE:ITEM_SUBTYPE MATERIAL:ETC\n"); + return CR_WRONG_USAGE; + } + item_str = parameters[0]; + material_str = parameters[1]; + + ItemTypeInfo item; + MaterialInfo material; + vector tokens; + + if (!item.find(item_str)) + { + out.printerr("Unrecognized item type!\n"); + return CR_FAILURE; + } + item_type = item.type; + item_subtype = item.subtype; + switch (item.type) + { + case df::item_type::INSTRUMENT: + case df::item_type::TOY: + case df::item_type::WEAPON: + case df::item_type::ARMOR: + case df::item_type::SHOES: + case df::item_type::SHIELD: + case df::item_type::HELM: + case df::item_type::GLOVES: + case df::item_type::AMMO: + case df::item_type::PANTS: + case df::item_type::SIEGEAMMO: + case df::item_type::TRAPCOMP: + case df::item_type::TOOL: + if (item_subtype == -1) + { + out.printerr("You must specify a valid subtype!\n"); + return CR_FAILURE; + } + default: + if (!material.find(material_str)) + { + out.printerr("Unrecognized material!\n"); + return CR_FAILURE; + } + mat_type = material.type; + mat_index = material.index; + break; + + case df::item_type::REMAINS: + case df::item_type::FISH: + case df::item_type::FISH_RAW: + case df::item_type::VERMIN: + case df::item_type::PET: + case df::item_type::EGG: + split_string(&tokens, material_str, ":"); + if (tokens.size() != 2) + { + out.printerr("You must specify a creature ID and caste for this item type!\n"); + return CR_FAILURE; + } + + mat_type = mat_index = -1; + for (size_t i = 0; i < world->raws.creatures.all.size(); i++) + { + df::creature_raw *creature = world->raws.creatures.all[i]; + if (creature->creature_id == tokens[0]) + { + for (size_t j = 0; j < creature->caste.size(); j++) + { + df::caste_raw *caste = creature->caste[j]; + if (creature->caste[j]->caste_id == tokens[1]) + { + mat_type = i; + mat_index = j; + break; + } + } + if (mat_type == -1) + { + out.printerr("The creature you specified has no such caste!\n"); + return CR_FAILURE; + } + } + } + if (mat_type == -1) + { + out.printerr("Unrecognized creature ID!\n"); + return CR_FAILURE; + } + break; + + case df::item_type::CORPSE: + case df::item_type::CORPSEPIECE: + case df::item_type::FOOD: + out.printerr("Cannot create that type of item!\n"); + return CR_FAILURE; + break; + } + + CoreSuspender suspend; + + df::unit *unit = Gui::getSelectedUnit(out, true); + if (!unit) + { + out.printerr("No unit selected!\n"); + return CR_FAILURE; + } + if (!Maps::IsValid()) + { + out.printerr("Map is not available.\n"); + return CR_FAILURE; + } + df::map_block *block = Maps::getTileBlock(unit->pos.x, unit->pos.y, unit->pos.z); + if (block == NULL) + { + out.printerr("Unit does not reside in a valid map block, somehow?\n"); + return CR_FAILURE; + } + + df::reaction_product_itemst *prod = df::allocate(); + prod->item_type = item_type; + prod->item_subtype = item_subtype; + prod->mat_type = mat_type; + prod->mat_index = mat_index; + prod->probability = 100; + prod->count = 1; + switch (item_type) + { + case df::item_type::BAR: + case df::item_type::POWDER_MISC: + case df::item_type::LIQUID_MISC: + case df::item_type::DRINK: + prod->product_dimension = 150; + break; + case df::item_type::THREAD: + prod->product_dimension = 15000; + break; + case df::item_type::CLOTH: + prod->product_dimension = 10000; + break; + default: + prod->product_dimension = 1; + break; + } + + bool result; +#if 1 + // Workaround for DF issue #0006273 + if (item_type == df::item_type::GLOVES) + result = makeItem(prod, unit, 1) && makeItem(prod, unit, 2); + else +#endif + result = makeItem(prod, unit); + + if (!result) + { + out.printerr("Failed to create item!\n"); + return CR_FAILURE; + } + return CR_OK; +}