Merge branches 'digAll', 'misery' and 'teledwarf' into experimental

develop
expwnent 2012-09-28 16:44:08 -04:00
commit ce7e21f869
3 changed files with 265 additions and 16 deletions

@ -115,6 +115,7 @@ if (BUILD_SUPPORTED)
DFHACK_PLUGIN(sort sort.cpp LINK_LIBRARIES lua) DFHACK_PLUGIN(sort sort.cpp LINK_LIBRARIES lua)
# not yet. busy with other crud again... # not yet. busy with other crud again...
#DFHACK_PLUGIN(versionosd versionosd.cpp) #DFHACK_PLUGIN(versionosd versionosd.cpp)
DFHACK_PLUGIN(misery misery.cpp)
endif() endif()

@ -23,33 +23,89 @@ DFhackCExport command_result plugin_shutdown ( color_ostream &out )
return CR_OK; return CR_OK;
} }
static int enable_fastdwarf = false; static bool enable_fastdwarf = false;
static bool enable_teledwarf = false;
DFhackCExport command_result plugin_onupdate ( color_ostream &out ) DFhackCExport command_result plugin_onupdate ( color_ostream &out )
{ {
// check run conditions // check run conditions
if(!world || !world->map.block_index || !enable_fastdwarf) if(!world || !world->map.block_index)
{ {
// give up if we shouldn't be running' enable_fastdwarf = enable_teledwarf = false;
return CR_OK; return CR_OK;
} }
int32_t race = ui->race_id; int32_t race = ui->race_id;
int32_t civ = ui->civ_id; int32_t civ = ui->civ_id;
for (size_t i = 0; i < world->units.all.size(); i++) if ( enable_fastdwarf ) {
{ for (size_t i = 0; i < world->units.all.size(); i++)
df::unit *unit = world->units.all[i]; {
df::unit *unit = world->units.all[i];
if (unit->race == race && unit->civ_id == civ && unit->counters.job_counter > 0)
unit->counters.job_counter = 0;
// could also patch the unit->job.current_job->completion_timer
}
}
if ( enable_teledwarf ) {
for (size_t i = 0; i < world->units.all.size(); i++)
{
df::unit *unit = world->units.all[i];
if (unit->race != race || unit->civ_id != civ || unit->path.dest.x == -30000)
continue;
if (unit->relations.draggee_id != -1 || unit->relations.dragger_id != -1)
continue;
if (unit->relations.following != 0)
continue;
if (unit->race == race && unit->civ_id == civ && unit->counters.job_counter > 0) //move immediately to destination
unit->counters.job_counter = 0; unit->pos.x = unit->path.dest.x;
// could also patch the unit->job.current_job->completion_timer unit->pos.y = unit->path.dest.y;
unit->pos.z = unit->path.dest.z;
}
} }
return CR_OK; return CR_OK;
} }
static command_result fastdwarf (color_ostream &out, vector <string> & parameters) static command_result fastdwarf (color_ostream &out, vector <string> & parameters)
{ {
if (parameters.size() == 1 && (parameters[0] == "0" || parameters[0] == "1")) if (parameters.size() == 1) {
if ( parameters[0] == "0" ) {
enable_fastdwarf = false;
enable_teledwarf = false;
} else if ( parameters[0] == "1" ) {
enable_fastdwarf = true;
enable_teledwarf = false;
} else {
out.print("Incorrect usage.\n");
return CR_OK;
}
} else if (parameters.size() == 2) {
if ( parameters[0] == "0" ) {
enable_fastdwarf = false;
} else if ( parameters[0] == "1" ) {
enable_fastdwarf = true;
} else {
out.print("Incorrect usage.\n");
return CR_OK;
}
if ( parameters[1] == "0" ) {
enable_teledwarf = false;
} else if ( parameters[1] == "1" ) {
enable_teledwarf = true;
} else {
out.print("Incorrect usage.\n");
return CR_OK;
}
} else if (parameters.size() == 0) {
//print status
out.print("Current state: fast = %d, teleport = %d.\n", enable_fastdwarf, enable_teledwarf);
} else {
out.print("Incorrect usage.\n");
return CR_OK;
}
/*if (parameters.size() == 1 && (parameters[0] == "0" || parameters[0] == "1"))
{ {
if (parameters[0] == "0") if (parameters[0] == "0")
enable_fastdwarf = 0; enable_fastdwarf = 0;
@ -62,7 +118,7 @@ static command_result fastdwarf (color_ostream &out, vector <string> & parameter
out.print("Makes your minions move at ludicrous speeds.\n" out.print("Makes your minions move at ludicrous speeds.\n"
"Activate with 'fastdwarf 1', deactivate with 'fastdwarf 0'.\n" "Activate with 'fastdwarf 1', deactivate with 'fastdwarf 0'.\n"
"Current state: %d.\n", enable_fastdwarf); "Current state: %d.\n", enable_fastdwarf);
} }*/
return CR_OK; return CR_OK;
} }
@ -70,8 +126,17 @@ static command_result fastdwarf (color_ostream &out, vector <string> & parameter
DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands) DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
{ {
commands.push_back(PluginCommand("fastdwarf", commands.push_back(PluginCommand("fastdwarf",
"enable/disable fastdwarf (parameter=0/1)", "enable/disable fastdwarf and teledwarf (parameters=0/1)",
fastdwarf)); fastdwarf, false,
"fastdwarf: controls speedydwarf and teledwarf. Speedydwarf makes dwarves move quickly and perform tasks quickly. Teledwarf makes dwarves move instantaneously, but do jobs at the same speed.\n"
"Usage:\n"
" fastdwarf 0 0: disable both speedydwarf and teledwarf\n"
" fastdwarf 0 1: disable speedydwarf, enable teledwarf\n"
" fastdwarf 1 0: enable speedydwarf, disable teledwarf\n"
" fastdwarf 1 1: enable speedydwarf, enable teledwarf\n"
" fastdwarf 0: disable speedydwarf, disable teledwarf\n"
" fastdwarf 1: enable speedydwarf, disable teledwarf\n"
));
return CR_OK; return CR_OK;
} }

@ -0,0 +1,183 @@
#include "PluginManager.h"
#include "Export.h"
#include "DataDefs.h"
#include "df/world.h"
#include "df/ui.h"
#include "df/unit.h"
#include "df/unit_thought.h"
#include "df/unit_thought_type.h"
#include <string>
#include <vector>
#include <map>
using namespace std;
using namespace DFHack;
static int factor = 1;
static map<int, int> processedThoughtCountTable;
//keep track of fake thoughts so you can remove them if requested
static vector<std::pair<int,int> > fakeThoughts;
static int count;
const int maxCount = 1000;
DFHACK_PLUGIN("misery");
command_result misery(color_ostream& out, vector<string>& parameters);
DFhackCExport command_result plugin_shutdown(color_ostream& out) {
factor = 1;
return CR_OK;
}
DFhackCExport command_result plugin_onupdate(color_ostream& out) {
static bool wasLoaded = false;
if ( factor == 1 || !df::global::world || !df::global::world->map.block_index ) {
if ( wasLoaded ) {
//we just unloaded the game: clear all data
factor = 1;
processedThoughtCountTable.clear();
fakeThoughts.clear();
wasLoaded = false;
}
return CR_OK;
}
if ( !wasLoaded ) {
wasLoaded = true;
}
if ( count < maxCount ) {
count++;
return CR_OK;
}
count = 0;
int32_t race_id = df::global::ui->race_id;
int32_t civ_id = df::global::ui->civ_id;
for ( size_t a = 0; a < df::global::world->units.all.size(); a++ ) {
df::unit* unit = df::global::world->units.all[a]; //TODO: consider units.active
//living, native units only
if ( unit->race != race_id || unit->civ_id != civ_id )
continue;
if ( unit->flags1.bits.dead )
continue;
int processedThoughtCount;
map<int,int>::iterator i = processedThoughtCountTable.find(unit->id);
if ( i == processedThoughtCountTable.end() ) {
processedThoughtCount = unit->status.recent_events.size();
processedThoughtCountTable[unit->id] = processedThoughtCount;
} else {
processedThoughtCount = (*i).second;
}
if ( processedThoughtCount == unit->status.recent_events.size() ) {
continue;
} else if ( processedThoughtCount > unit->status.recent_events.size() ) {
processedThoughtCount = unit->status.recent_events.size();
}
//don't reprocess any old thoughts
vector<df::unit_thought*> newThoughts;
for ( size_t b = processedThoughtCount; b < unit->status.recent_events.size(); b++ ) {
df::unit_thought* oldThought = unit->status.recent_events[b];
const char* bob = ENUM_ATTR(unit_thought_type, value, oldThought->type);
if ( bob[0] != '-' ) {
//out.print("unit %4d: old thought value = %s\n", unit->id, bob);
continue;
}
/*out.print("unit %4d: Duplicating thought type %d (%s), value %s, age %d, subtype %d, severity %d\n",
unit->id,
oldThought->type.value,
ENUM_ATTR(unit_thought_type, caption, (oldThought->type)),
//df::enum_traits<df::unit_thought_type>::attr_table[oldThought->type].caption
bob,
oldThought->age,
oldThought->subtype,
oldThought->severity
);*/
//add duplicate thoughts to the temp list
for ( size_t c = 0; c < factor; c++ ) {
df::unit_thought* thought = new df::unit_thought;
thought->type = unit->status.recent_events[b]->type;
thought->age = unit->status.recent_events[b]->age;
thought->subtype = unit->status.recent_events[b]->subtype;
thought->severity = unit->status.recent_events[b]->severity;
newThoughts.push_back(thought);
}
}
for ( size_t b = 0; b < newThoughts.size(); b++ ) {
fakeThoughts.push_back(std::pair<int, int>(a, unit->status.recent_events.size()));
unit->status.recent_events.push_back(newThoughts[b]);
}
processedThoughtCountTable[unit->id] = unit->status.recent_events.size();
}
return CR_OK;
}
DFhackCExport command_result plugin_init(color_ostream& out, vector<PluginCommand> &commands) {
commands.push_back(PluginCommand("misery", "increase the intensity of negative dwarven thoughts",
&misery, false,
"misery: When enabled, every new negative dwarven thought will be multiplied by a factor (2 by default).\n"
"Usage:\n"
" misery enable n\n"
" enable misery with optional magnitude n. If specified, n must be positive.\n"
" misery n\n"
" same as \"misery enable n\"\n"
" misery enable\n"
" same as \"misery enable 2\"\n"
" misery disable\n"
" stop adding new negative thoughts. This will not remove existing duplicated thoughts. Equivalent to \"misery 1\"\n"
" misery clear\n"
" remove fake thoughts added in this session of DF. Saving makes them permanent! Does not change factor.\n\n"
));
return CR_OK;
}
command_result misery(color_ostream &out, vector<string>& parameters) {
if ( !df::global::world || !df::global::world->map.block_index ) {
out.printerr("misery can only be enabled in fortress mode with a fully-loaded game.\n");
return CR_FAILURE;
}
if ( parameters.size() < 1 || parameters.size() > 2 ) {
return CR_WRONG_USAGE;
}
if ( parameters[0] == "disable" ) {
if ( parameters.size() > 1 ) {
return CR_WRONG_USAGE;
}
factor = 1;
return CR_OK;
} else if ( parameters[0] == "enable" ) {
factor = 2;
if ( parameters.size() == 2 ) {
factor = atoi(parameters[1].c_str());
if ( factor < 1 ) {
out.printerr("Second argument must be a positive integer.\n");
return CR_WRONG_USAGE;
}
}
} else if ( parameters[0] == "clear" ) {
for ( size_t a = 0; a < fakeThoughts.size(); a++ ) {
int dorfIndex = fakeThoughts[a].first;
int thoughtIndex = fakeThoughts[a].second;
df::global::world->units.all[dorfIndex]->status.recent_events[thoughtIndex]->age = 1000000;
}
fakeThoughts.clear();
} else {
int a = atoi(parameters[0].c_str());
if ( a < 1 ) {
return CR_WRONG_USAGE;
}
factor = a;
}
return CR_OK;
}