develop
Petr Mrázek 2012-09-29 01:31:12 +02:00
commit 4258d1eb83
4 changed files with 409 additions and 18 deletions

@ -126,6 +126,7 @@ if (BUILD_SUPPORTED)
DFHACK_PLUGIN(add-spatter add-spatter.cpp) DFHACK_PLUGIN(add-spatter add-spatter.cpp)
# 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()

@ -24,7 +24,7 @@ command_result diglx (color_ostream &out, vector <string> & parameters);
command_result digauto (color_ostream &out, vector <string> & parameters); command_result digauto (color_ostream &out, vector <string> & parameters);
command_result digexp (color_ostream &out, vector <string> & parameters); command_result digexp (color_ostream &out, vector <string> & parameters);
command_result digcircle (color_ostream &out, vector <string> & parameters); command_result digcircle (color_ostream &out, vector <string> & parameters);
command_result digtype (color_ostream &out, vector <string> & parameters);
DFHACK_PLUGIN("dig"); DFHACK_PLUGIN("dig");
@ -57,6 +57,18 @@ DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <Plug
commands.push_back(PluginCommand("digexp","Select or designate an exploratory pattern. Use 'digexp ?' for help.",digexp)); commands.push_back(PluginCommand("digexp","Select or designate an exploratory pattern. Use 'digexp ?' for help.",digexp));
commands.push_back(PluginCommand("digcircle","Dig designate a circle (filled or hollow) with given radius.",digcircle)); commands.push_back(PluginCommand("digcircle","Dig designate a circle (filled or hollow) with given radius.",digcircle));
//commands.push_back(PluginCommand("digauto","Mark a tile for continuous digging.",autodig)); //commands.push_back(PluginCommand("digauto","Mark a tile for continuous digging.",autodig));
commands.push_back(PluginCommand("digtype", "Dig all veins of a given type.", digtype,Gui::cursor_hotkey,
"For every tile on the map of the same vein type as the selected tile, this command designates it to have the same designation as the selected tile. If the selected tile has no designation, they will be dig designated.\n"
"If an argument is given, the designation of the selected tile is ignored, and all appropriate tiles are set to the specified designation.\n"
"Options:\n"
" dig\n"
" channel\n"
" ramp\n"
" updown - up/down stairs\n"
" up - up stairs\n"
" down - down stairs\n"
" clear - clear designation\n"
));
return CR_OK; return CR_OK;
} }
@ -951,7 +963,7 @@ command_result digexp (color_ostream &out, vector <string> & parameters)
mx.setDesignationAt(pos,des); mx.setDesignationAt(pos,des);
} }
} }
mx.WriteAll(); mx.WriteAll();
} }
else for(uint32_t x = 0; x < x_max; x++) else for(uint32_t x = 0; x < x_max; x++)
{ {
@ -1129,6 +1141,7 @@ command_result digv (color_ostream &out, vector <string> & parameters)
} }
} }
MCache->WriteAll(); MCache->WriteAll();
delete MCache;
return CR_OK; return CR_OK;
} }
@ -1342,6 +1355,7 @@ command_result digl (color_ostream &out, vector <string> & parameters)
} }
} }
MCache->WriteAll(); MCache->WriteAll();
delete MCache;
return CR_OK; return CR_OK;
} }
@ -1350,3 +1364,120 @@ command_result digauto (color_ostream &out, vector <string> & parameters)
{ {
return CR_NOT_IMPLEMENTED; return CR_NOT_IMPLEMENTED;
} }
command_result digtype (color_ostream &out, vector <string> & parameters)
{
//mostly copy-pasted from digv
CoreSuspender suspend;
if ( parameters.size() > 1 )
{
out.printerr("Too many parameters.\n");
return CR_FAILURE;
}
uint32_t targetDigType;
if ( parameters.size() == 1 )
{
string parameter = parameters[0];
if ( parameter == "clear" )
targetDigType = tile_dig_designation::No;
else if ( parameter == "dig" )
targetDigType = tile_dig_designation::Default;
else if ( parameter == "updown" )
targetDigType = tile_dig_designation::UpDownStair;
else if ( parameter == "channel" )
targetDigType = tile_dig_designation::Channel;
else if ( parameter == "ramp" )
targetDigType = tile_dig_designation::Ramp;
else if ( parameter == "down" )
targetDigType = tile_dig_designation::DownStair;
else if ( parameter == "up" )
targetDigType = tile_dig_designation::UpStair;
else
{
out.printerr("Invalid parameter.\n");
return CR_FAILURE;
}
}
else
{
targetDigType = -1;
}
if (!Maps::IsValid())
{
out.printerr("Map is not available!\n");
return CR_FAILURE;
}
int32_t cx, cy, cz;
uint32_t xMax,yMax,zMax;
Maps::getSize(xMax,yMax,zMax);
uint32_t tileXMax = xMax * 16;
uint32_t tileYMax = yMax * 16;
Gui::getCursorCoords(cx,cy,cz);
if (cx == -30000)
{
out.printerr("Cursor is not active. Point the cursor at a vein.\n");
return CR_FAILURE;
}
DFHack::DFCoord xy ((uint32_t)cx,(uint32_t)cy,cz);
MapExtras::MapCache * mCache = new MapExtras::MapCache;
df::tile_designation baseDes = mCache->designationAt(xy);
df::tiletype tt = mCache->tiletypeAt(xy);
int16_t veinmat = mCache->veinMaterialAt(xy);
if( veinmat == -1 )
{
out.printerr("This tile is not a vein.\n");
delete mCache;
return CR_FAILURE;
}
out.print("(%d,%d,%d) tiletype: %d, veinmat: %d, designation: 0x%x ... DIGGING!\n", cx,cy,cz, tt, veinmat, baseDes.whole);
if ( targetDigType != -1 )
{
baseDes.bits.dig = (tile_dig_designation::tile_dig_designation)targetDigType;
}
else
{
if ( baseDes.bits.dig == tile_dig_designation::No )
{
baseDes.bits.dig = tile_dig_designation::Default;
}
}
for( uint32_t z = 0; z < zMax; z++ )
{
for( uint32_t x = 1; x < tileXMax-1; x++ )
{
for( uint32_t y = 1; y < tileYMax-1; y++ )
{
DFHack::DFCoord current(x,y,z);
int16_t vmat2 = mCache->veinMaterialAt(current);
if ( vmat2 != veinmat )
continue;
tt = mCache->tiletypeAt(current);
if (!DFHack::isWallTerrain(tt))
continue;
//designate it for digging
df::tile_designation des = mCache->designationAt(current);
if ( !mCache->testCoord(current) )
{
out.printerr("testCoord failed at (%d,%d,%d)\n", x, y, z);
delete mCache;
return CR_FAILURE;
}
df::tile_designation designation = mCache->designationAt(current);
designation.bits.dig = baseDes.bits.dig;
mCache->setDesignationAt(current, designation);
}
}
}
mCache->WriteAll();
delete mCache;
return CR_OK;
}

@ -2,6 +2,7 @@
#include "Console.h" #include "Console.h"
#include "Export.h" #include "Export.h"
#include "PluginManager.h" #include "PluginManager.h"
#include "modules/MapCache.h"
#include "DataDefs.h" #include "DataDefs.h"
#include "df/ui.h" #include "df/ui.h"
@ -23,33 +24,99 @@ 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; if (unit->race == race && unit->civ_id == civ && unit->counters.job_counter > 0)
// could also patch the unit->job.current_job->completion_timer unit->counters.job_counter = 0;
// could also patch the unit->job.current_job->completion_timer
}
}
if ( enable_teledwarf ) {
MapExtras::MapCache *MCache = new MapExtras::MapCache();
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;
MapExtras::Block* block = MCache->BlockAtTile(unit->pos);
df::coord2d pos(unit->pos.x % 16, unit->pos.y % 16);
df::tile_occupancy occ = block->OccupancyAt(pos);
occ.bits.unit = 0;
occ.bits.unit_grounded = 0;
block->setOccupancyAt(pos, occ);
//move immediately to destination
unit->pos.x = unit->path.dest.x;
unit->pos.y = unit->path.dest.y;
unit->pos.z = unit->path.dest.z;
}
MCache->WriteAll();
delete MCache;
} }
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 +129,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 +137,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;
}