2012-01-27 08:47:14 -07:00
|
|
|
/*
|
2012-01-07 08:21:07 -07:00
|
|
|
https://github.com/peterix/dfhack
|
|
|
|
Copyright (c) 2009-2011 Petr Mrázek (peterix@gmail.com)
|
|
|
|
|
|
|
|
This software is provided 'as-is', without any express or implied
|
|
|
|
warranty. In no event will the authors be held liable for any
|
|
|
|
damages arising from the use of this software.
|
|
|
|
|
|
|
|
Permission is granted to anyone to use this software for any
|
|
|
|
purpose, including commercial applications, and to alter it and
|
|
|
|
redistribute it freely, subject to the following restrictions:
|
|
|
|
|
|
|
|
1. The origin of this software must not be misrepresented; you must
|
|
|
|
not claim that you wrote the original software. If you use this
|
|
|
|
software in a product, an acknowledgment in the product documentation
|
|
|
|
would be appreciated but is not required.
|
|
|
|
|
|
|
|
2. Altered source versions must be plainly marked as such, and
|
|
|
|
must not be misrepresented as being the original software.
|
|
|
|
|
|
|
|
3. This notice may not be removed or altered from any source
|
|
|
|
distribution.
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
#include "Internal.h"
|
|
|
|
|
|
|
|
#include <string>
|
|
|
|
#include <vector>
|
|
|
|
#include <map>
|
|
|
|
#include <cassert>
|
|
|
|
using namespace std;
|
|
|
|
|
|
|
|
#include "Core.h"
|
|
|
|
#include "PluginManager.h"
|
2012-01-08 09:02:12 -07:00
|
|
|
#include "MiscUtils.h"
|
2012-01-07 08:21:07 -07:00
|
|
|
|
|
|
|
#include "modules/Job.h"
|
|
|
|
#include "modules/Materials.h"
|
2012-01-09 05:20:17 -07:00
|
|
|
#include "modules/Items.h"
|
2012-01-07 08:21:07 -07:00
|
|
|
|
|
|
|
#include "DataDefs.h"
|
2012-01-15 13:54:14 -07:00
|
|
|
#include "df/world.h"
|
|
|
|
#include "df/ui.h"
|
|
|
|
#include "df/job.h"
|
|
|
|
#include "df/job_item.h"
|
|
|
|
#include "df/job_list_link.h"
|
|
|
|
#include "df/general_ref.h"
|
|
|
|
#include "df/general_ref_unit_workerst.h"
|
|
|
|
#include "df/general_ref_building_holderst.h"
|
2012-01-07 08:21:07 -07:00
|
|
|
|
|
|
|
using namespace DFHack;
|
|
|
|
using namespace df::enums;
|
|
|
|
|
|
|
|
df::job *DFHack::cloneJobStruct(df::job *job)
|
|
|
|
{
|
|
|
|
df::job *pnew = new df::job(*job);
|
|
|
|
|
|
|
|
// Clean out transient fields
|
|
|
|
pnew->flags.whole = 0;
|
|
|
|
pnew->flags.bits.repeat = job->flags.bits.repeat;
|
|
|
|
pnew->flags.bits.suspend = job->flags.bits.suspend;
|
|
|
|
|
|
|
|
pnew->list_link = NULL;
|
|
|
|
pnew->completion_timer = -1;
|
|
|
|
pnew->items.clear();
|
|
|
|
pnew->misc_links.clear();
|
|
|
|
|
|
|
|
// Clone refs
|
|
|
|
for (int i = pnew->references.size()-1; i >= 0; i--)
|
|
|
|
{
|
|
|
|
df::general_ref *ref = pnew->references[i];
|
|
|
|
|
|
|
|
if (virtual_cast<df::general_ref_unit_workerst>(ref))
|
2012-01-08 09:02:12 -07:00
|
|
|
vector_erase_at(pnew->references, i);
|
2012-01-07 08:21:07 -07:00
|
|
|
else
|
|
|
|
pnew->references[i] = ref->clone();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Clone items
|
|
|
|
for (int i = pnew->job_items.size()-1; i >= 0; i--)
|
|
|
|
pnew->job_items[i] = new df::job_item(*pnew->job_items[i]);
|
|
|
|
|
|
|
|
return pnew;
|
|
|
|
}
|
|
|
|
|
|
|
|
void DFHack::deleteJobStruct(df::job *job)
|
|
|
|
{
|
|
|
|
if (!job)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Only allow free-floating job structs
|
|
|
|
assert(!job->list_link && job->items.empty() && job->misc_links.empty());
|
|
|
|
|
|
|
|
for (int i = job->references.size()-1; i >= 0; i--)
|
|
|
|
delete job->references[i];
|
|
|
|
|
|
|
|
for (int i = job->job_items.size()-1; i >= 0; i--)
|
|
|
|
delete job->job_items[i];
|
|
|
|
|
|
|
|
delete job;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define CMP(field) (a.field == b.field)
|
|
|
|
|
|
|
|
bool DFHack::operator== (const df::job_item &a, const df::job_item &b)
|
|
|
|
{
|
|
|
|
if (!(CMP(item_type) && CMP(item_subtype) &&
|
|
|
|
CMP(mat_type) && CMP(mat_index) &&
|
|
|
|
CMP(flags1.whole) && CMP(quantity) && CMP(vector_id) &&
|
|
|
|
CMP(flags2.whole) && CMP(flags3.whole) &&
|
|
|
|
CMP(metal_ore) && CMP(reaction_class) &&
|
|
|
|
CMP(has_material_reaction_product) &&
|
|
|
|
CMP(min_dimension) && CMP(reagent_index) &&
|
|
|
|
CMP(reaction_id) && CMP(has_tool_use) &&
|
|
|
|
CMP(contains.size())))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
for (int i = a.contains.size()-1; i >= 0; i--)
|
|
|
|
if (a.contains[i] != b.contains[i])
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool DFHack::operator== (const df::job &a, const df::job &b)
|
|
|
|
{
|
|
|
|
if (!(CMP(job_type) && CMP(unk2) &&
|
|
|
|
CMP(mat_type) && CMP(mat_index) &&
|
|
|
|
CMP(item_subtype) && CMP(item_category.whole) &&
|
|
|
|
CMP(hist_figure_id) && CMP(material_category.whole) &&
|
|
|
|
CMP(reaction_name) && CMP(job_items.size())))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
for (int i = a.job_items.size()-1; i >= 0; i--)
|
|
|
|
if (!(*a.job_items[i] == *b.job_items[i]))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2012-03-10 04:55:42 -07:00
|
|
|
static void print_job_item_details(color_ostream &out, df::job *job, unsigned idx, df::job_item *item)
|
2012-01-07 08:21:07 -07:00
|
|
|
{
|
2012-01-09 05:20:17 -07:00
|
|
|
ItemTypeInfo info(item);
|
2012-03-10 04:55:42 -07:00
|
|
|
out << " Input Item " << (idx+1) << ": " << info.toString();
|
2012-01-09 05:20:17 -07:00
|
|
|
|
2012-01-07 08:21:07 -07:00
|
|
|
if (item->quantity != 1)
|
2012-03-10 04:55:42 -07:00
|
|
|
out << "; quantity=" << item->quantity;
|
2012-01-07 08:21:07 -07:00
|
|
|
if (item->min_dimension >= 0)
|
2012-03-10 04:55:42 -07:00
|
|
|
out << "; min_dimension=" << item->min_dimension;
|
|
|
|
out << endl;
|
2012-01-07 08:21:07 -07:00
|
|
|
|
|
|
|
MaterialInfo mat(item);
|
|
|
|
if (mat.isValid() || item->metal_ore >= 0) {
|
2012-03-10 04:55:42 -07:00
|
|
|
out << " material: " << mat.toString();
|
2012-01-07 08:21:07 -07:00
|
|
|
if (item->metal_ore >= 0)
|
2012-03-10 04:55:42 -07:00
|
|
|
out << "; ore of " << MaterialInfo(0,item->metal_ore).toString();
|
|
|
|
out << endl;
|
2012-01-07 08:21:07 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if (item->flags1.whole)
|
2012-03-10 04:55:42 -07:00
|
|
|
out << " flags1: " << bitfieldToString(item->flags1) << endl;
|
2012-01-07 08:21:07 -07:00
|
|
|
if (item->flags2.whole)
|
2012-03-10 04:55:42 -07:00
|
|
|
out << " flags2: " << bitfieldToString(item->flags2) << endl;
|
2012-01-07 08:21:07 -07:00
|
|
|
if (item->flags3.whole)
|
2012-03-10 04:55:42 -07:00
|
|
|
out << " flags3: " << bitfieldToString(item->flags3) << endl;
|
2012-01-07 08:21:07 -07:00
|
|
|
|
|
|
|
if (!item->reaction_class.empty())
|
2012-03-10 04:55:42 -07:00
|
|
|
out << " reaction class: " << item->reaction_class << endl;
|
2012-01-07 08:21:07 -07:00
|
|
|
if (!item->has_material_reaction_product.empty())
|
2012-03-10 04:55:42 -07:00
|
|
|
out << " reaction product: " << item->has_material_reaction_product << endl;
|
2012-01-07 08:21:07 -07:00
|
|
|
if (item->has_tool_use >= 0)
|
2012-03-10 04:55:42 -07:00
|
|
|
out << " tool use: " << ENUM_KEY_STR(tool_uses, item->has_tool_use) << endl;
|
2012-01-07 08:21:07 -07:00
|
|
|
}
|
|
|
|
|
2012-03-10 04:55:42 -07:00
|
|
|
void DFHack::printJobDetails(color_ostream &out, df::job *job)
|
2012-01-07 08:21:07 -07:00
|
|
|
{
|
2012-03-10 04:55:42 -07:00
|
|
|
out.color(job->flags.bits.suspend ? Console::COLOR_DARKGREY : Console::COLOR_GREY);
|
|
|
|
out << "Job " << job->id << ": " << ENUM_KEY_STR(job_type,job->job_type);
|
2012-01-07 08:21:07 -07:00
|
|
|
if (job->flags.whole)
|
2012-03-10 04:55:42 -07:00
|
|
|
out << " (" << bitfieldToString(job->flags) << ")";
|
|
|
|
out << endl;
|
|
|
|
out.reset_color();
|
2012-01-07 08:21:07 -07:00
|
|
|
|
2012-01-09 05:20:17 -07:00
|
|
|
df::item_type itype = ENUM_ATTR(job_type, item, job->job_type);
|
|
|
|
|
2012-01-07 08:21:07 -07:00
|
|
|
MaterialInfo mat(job);
|
2012-01-09 05:20:17 -07:00
|
|
|
if (itype == item_type::FOOD)
|
|
|
|
mat.decode(-1);
|
|
|
|
|
2012-01-07 08:21:07 -07:00
|
|
|
if (mat.isValid() || job->material_category.whole)
|
|
|
|
{
|
2012-03-10 04:55:42 -07:00
|
|
|
out << " material: " << mat.toString();
|
2012-01-07 08:21:07 -07:00
|
|
|
if (job->material_category.whole)
|
2012-03-10 04:55:42 -07:00
|
|
|
out << " (" << bitfieldToString(job->material_category) << ")";
|
|
|
|
out << endl;
|
2012-01-07 08:21:07 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if (job->item_subtype >= 0 || job->item_category.whole)
|
2012-01-09 05:20:17 -07:00
|
|
|
{
|
|
|
|
ItemTypeInfo iinfo(itype, job->item_subtype);
|
|
|
|
|
2012-03-10 04:55:42 -07:00
|
|
|
out << " item: " << iinfo.toString()
|
2012-01-07 08:21:07 -07:00
|
|
|
<< " (" << bitfieldToString(job->item_category) << ")" << endl;
|
2012-01-09 05:20:17 -07:00
|
|
|
}
|
2012-01-07 08:21:07 -07:00
|
|
|
|
|
|
|
if (job->hist_figure_id >= 0)
|
2012-03-10 04:55:42 -07:00
|
|
|
out << " figure: " << job->hist_figure_id << endl;
|
2012-01-07 08:21:07 -07:00
|
|
|
|
|
|
|
if (!job->reaction_name.empty())
|
2012-03-10 04:55:42 -07:00
|
|
|
out << " reaction: " << job->reaction_name << endl;
|
2012-01-07 08:21:07 -07:00
|
|
|
|
2012-01-31 09:55:38 -07:00
|
|
|
for (size_t i = 0; i < job->job_items.size(); i++)
|
2012-03-10 04:55:42 -07:00
|
|
|
print_job_item_details(out, job, i, job->job_items[i]);
|
2012-01-07 08:21:07 -07:00
|
|
|
}
|
2012-01-08 09:02:12 -07:00
|
|
|
|
|
|
|
df::building *DFHack::getJobHolder(df::job *job)
|
|
|
|
{
|
2012-01-31 09:55:38 -07:00
|
|
|
for (size_t i = 0; i < job->references.size(); i++)
|
2012-01-08 09:02:12 -07:00
|
|
|
{
|
|
|
|
VIRTUAL_CAST_VAR(ref, df::general_ref_building_holderst, job->references[i]);
|
|
|
|
if (ref)
|
|
|
|
return ref->getBuilding();
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool DFHack::linkJobIntoWorld(df::job *job, bool new_id)
|
|
|
|
{
|
|
|
|
using df::global::world;
|
|
|
|
using df::global::job_next_id;
|
|
|
|
|
|
|
|
assert(!job->list_link);
|
|
|
|
|
|
|
|
if (new_id) {
|
|
|
|
job->id = (*job_next_id)++;
|
|
|
|
|
|
|
|
job->list_link = new df::job_list_link();
|
|
|
|
job->list_link->item = job;
|
|
|
|
linked_list_append(&world->job_list, job->list_link);
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
df::job_list_link *ins_pos = &world->job_list;
|
|
|
|
while (ins_pos->next && ins_pos->next->item->id < job->id)
|
|
|
|
ins_pos = ins_pos->next;
|
|
|
|
|
|
|
|
if (ins_pos->next && ins_pos->next->item->id == job->id)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
job->list_link = new df::job_list_link();
|
|
|
|
job->list_link->item = job;
|
|
|
|
linked_list_insert_after(ins_pos, job->list_link);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|