Add a hotkey command to duplicate jobs in workshops.

develop
Alexander Gavrilov 2012-01-04 19:39:38 +04:00
parent 99dda069de
commit 284009e873
4 changed files with 117 additions and 3 deletions

@ -1094,6 +1094,7 @@
<Address name='ui_look_cursor'/>
<Address name='ui_workshop_job_cursor'/>
<Address name='ui_workshop_in_add'/>
<Address name='job_next_id'/>
</Group>
</Offsets>
</Base>
@ -2345,6 +2346,8 @@
<Address name='ui_look_cursor' value='0xedeb98'/>
<Address name='ui_workshop_job_cursor' value='0x14ec79c'/>
<Address name='ui_workshop_in_add' value='0xeb0992'/>
<Address name='job_next_id' value='0xe18290'/>
</Group>
</Offsets>
cmake
@ -3230,6 +3233,8 @@
<!--<Address name='ui_look_cursor' value=''/>-->
<Address name='ui_workshop_job_cursor' value='0x93f0644'/>
<Address name='ui_workshop_in_add' value='0x93f0651'/>
<Address name='job_next_id' value='0x961d940'/>
</Group>
</Offsets>
</Version>

@ -204,6 +204,7 @@ namespace df {
GLOBAL(gview,interface) \
GLOBAL(init,init) \
GLOBAL(d_init,d_init) \
SIMPLE_GLOBAL(job_next_id,int) \
SIMPLE_GLOBAL(ui_look_cursor,int) \
SIMPLE_GLOBAL(ui_workshop_job_cursor,int) \
SIMPLE_GLOBAL(ui_workshop_in_add,bool) \

@ -172,6 +172,20 @@ CT *binsearch_in_vector(const std::vector<CT*> &vec, FT CT::*field, FT value)
return idx < 0 ? NULL : vec[idx];
}
/*
* List
*/
template<typename Link>
Link *linked_list_append(Link *head, Link *tail)
{
while (head->next)
head = head->next;
head->next = tail;
tail->prev = head;
return tail;
}
/*
* MISC
*/

@ -17,8 +17,11 @@
#include <df/building_furnacest.h>
#include <df/job.h>
#include <df/job_item.h>
#include <df/job_list_link.h>
#include <df/item.h>
#include <df/tool_uses.h>
#include <df/general_ref.h>
#include <df/general_ref_unit_workerst.h>
using std::vector;
using std::string;
@ -30,13 +33,16 @@ using df::global::world;
using df::global::ui;
using df::global::ui_build_selector;
using df::global::ui_workshop_job_cursor;
using df::global::job_next_id;
static bool wokshop_job_hotkey(Core *c, df::viewscreen *top);
static bool build_selector_hotkey(Core *c, df::viewscreen *top);
/* Plugin registration */
static bool workshop_job_hotkey(Core *c, df::viewscreen *top);
static bool build_selector_hotkey(Core *c, df::viewscreen *top);
static bool job_material_hotkey(Core *c, df::viewscreen *top);
static command_result job_material(Core *c, vector <string> & parameters);
static command_result job_material(Core *c, vector <string> & parameters);
static command_result job_duplicate(Core *c, vector <string> & parameters);
static command_result job_cmd(Core *c, vector <string> & parameters);
DFhackCExport const char * plugin_name ( void )
@ -75,6 +81,17 @@ DFhackCExport command_result plugin_init (Core *c, std::vector <PluginCommand> &
);
}
if (ui_workshop_job_cursor && job_next_id) {
commands.push_back(
PluginCommand(
"job-duplicate", "Duplicate the selected job in a workshop.",
job_duplicate, workshop_job_hotkey,
" - In 'q' mode, when a job is highlighted within a workshop\n"
" or furnace building, instantly duplicates the job.\n"
)
);
}
return CR_OK;
}
@ -83,6 +100,8 @@ DFhackCExport command_result plugin_shutdown ( Core * c )
return CR_OK;
}
/* UI state guards */
static bool workshop_job_hotkey(Core *c, df::viewscreen *top)
{
using namespace ui_sidebar_mode;
@ -150,6 +169,8 @@ static bool job_material_hotkey(Core *c, df::viewscreen *top)
build_selector_hotkey(c, top);
}
/* job-material implementation */
static df::job *getWorkshopJob(Core *c)
{
df::building *selected = world->selected_building;
@ -288,6 +309,79 @@ static command_result job_material(Core * c, vector <string> & parameters)
return CR_WRONG_USAGE;
}
/* job-duplicate implementation */
static df::job *clone_job(df::job *job)
{
df::job *pnew = new df::job(*job);
pnew->id = (*job_next_id)++;
// Clean out transient fields
pnew->flags.whole = 0;
pnew->flags.bits.repeat = job->flags.bits.repeat;
pnew->completion_timer = -1;
pnew->items.clear();
pnew->misc_links.clear();
// Link the job into the global list
pnew->list_link = new df::job_list_link();
pnew->list_link->item = pnew;
linked_list_append(&world->job_list, pnew->list_link);
// 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))
pnew->references.erase(pnew->references.begin()+i);
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;
}
static command_result job_duplicate(Core * c, vector <string> & parameters)
{
if (!parameters.empty())
return CR_WRONG_USAGE;
df::job *job = getWorkshopJob(c);
if (!job)
return CR_FAILURE;
if (!job->misc_links.empty() || job->job_items.empty())
{
c->con.printerr("Cannot duplicate job %s\n", ENUM_KEY_STR(job_type,job->job_type));
return CR_FAILURE;
}
df::building *building = world->selected_building;
if (building->jobs.size() >= 10)
{
c->con.printerr("Job list is already full.\n");
return CR_FAILURE;
}
// Actually clone
df::job *pnew = clone_job(job);
int pos = ++*ui_workshop_job_cursor;
building->jobs.insert(building->jobs.begin()+pos, pnew);
return CR_OK;
}
/* Main job command implementation */
static void print_job_item_details(Core *c, df::job *job, df::job_item *item)
{
c->con << " Input Item: " << ENUM_KEY_STR(item_type,item->item_type);