Merged grow and immolate tools into plants plugin.

develop
Petr Mrázek 2011-08-02 02:21:25 +02:00
parent b0659224fa
commit 6cc66d3434
19 changed files with 259 additions and 560 deletions

@ -40,6 +40,7 @@ using namespace std;
#include "dfhack/Console.h"
#include "dfhack/Module.h"
#include "dfhack/VersionInfoFactory.h"
#include "dfhack/VersionInfo.h"
#include "dfhack/PluginManager.h"
#include "ModuleFactory.h"
#include "dfhack/modules/Gui.h"
@ -51,6 +52,7 @@ using namespace DFHack;
#include <stdio.h>
#include <iomanip>
#include <stdlib.h>
#include <fstream>
#include "tinythread.h"
using namespace tthread;
@ -392,7 +394,13 @@ bool Core::Init()
vif = new DFHack::VersionInfoFactory("Memory.xml");
p = new DFHack::Process(vif);
vinfo = p->getDescriptor();
// dump offsets to a file
std::ofstream dump("offsets.log");
if(!dump.fail())
{
dump << vinfo->PrintOffsets();
dump.close();
}
// init the console.
Gui * g = getGui();
if(g->init)

@ -130,7 +130,7 @@ endif()
DFHACK_PLUGIN(reveal reveal.cpp)
DFHACK_PLUGIN(probe probe.cpp)
DFHACK_PLUGIN(grow grow.cpp)
DFHACK_PLUGIN(plants plants.cpp)
DFHACK_PLUGIN(prospector prospector.cpp)
DFHACK_PLUGIN(rawdump rawdump.cpp)
DFHACK_PLUGIN(cleanmap cleanmap.cpp)

@ -1,103 +0,0 @@
#include <iostream>
#include <iomanip>
#include <map>
#include <algorithm>
#include <vector>
#include <string>
#include <dfhack/Core.h>
#include <dfhack/Console.h>
#include <dfhack/Export.h>
#include <dfhack/PluginManager.h>
#include <dfhack/modules/Vegetation.h>
#include <dfhack/modules/Maps.h>
#include <dfhack/modules/Gui.h>
#include <dfhack/TileTypes.h>
#include <dfhack/extra/MapExtras.h>
using std::vector;
using std::string;
using namespace DFHack;
DFhackCExport command_result df_grow (Core * c, vector <string> & parameters);
DFhackCExport const char * plugin_name ( void )
{
return "grow";
}
DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand> &commands)
{
commands.clear();
commands.push_back(PluginCommand("grow", "Grows saplings into trees (with active cursor, only the targetted one).", df_grow));
return CR_OK;
}
DFhackCExport command_result plugin_shutdown ( Core * c )
{
return CR_OK;
}
DFhackCExport command_result df_grow (Core * c, vector <string> & parameters)
{
//uint32_t x_max = 0, y_max = 0, z_max = 0;
c->Suspend();
DFHack::Maps *maps = c->getMaps();
Console & con = c->con;
if (!maps->Start())
{
con.printerr("Cannot get map info!\n");
c->Resume();
return CR_FAILURE;
}
//maps->getSize(x_max, y_max, z_max);
MapExtras::MapCache map(maps);
DFHack::Vegetation *veg = c->getVegetation();
if (!veg->all_plants)
{
con.printerr("Unable to read vegetation!\n");
c->Resume();
return CR_FAILURE;
}
DFHack::Gui *Gui = c->getGui();
int32_t x,y,z;
if(Gui->getCursorCoords(x,y,z))
{
vector<DFHack::df_plant *> * alltrees;
if(maps->ReadVegetation(x/16,y/16,z,alltrees))
{
for(size_t i = 0 ; i < alltrees->size(); i++)
{
DFHack::df_plant * tree = alltrees->at(i);
if(tree->x == x && tree->y == y && tree->z == z)
{
if(DFHack::tileShape(map.tiletypeAt(DFHack::DFCoord(x,y,z))) == DFHack::SAPLING_OK)
{
tree->grow_counter = DFHack::sapling_to_tree_threshold;
}
break;
}
}
}
}
else
{
int grown = 0;
for(size_t i = 0 ; i < veg->all_plants->size(); i++)
{
DFHack::df_plant *p = veg->all_plants->at(i);
uint16_t ttype = map.tiletypeAt(DFHack::DFCoord(p->x,p->y,p->z));
if(!p->is_shrub && DFHack::tileShape(ttype) == DFHack::SAPLING_OK)
{
p->grow_counter = DFHack::sapling_to_tree_threshold;
}
}
}
// Cleanup
veg->Finish();
maps->Finish();
c->Resume();
return CR_OK;
}

@ -0,0 +1,249 @@
#include <iostream>
#include <iomanip>
#include <map>
#include <algorithm>
#include <vector>
#include <string>
#include <dfhack/Core.h>
#include <dfhack/Console.h>
#include <dfhack/Export.h>
#include <dfhack/PluginManager.h>
#include <dfhack/modules/Vegetation.h>
#include <dfhack/modules/Maps.h>
#include <dfhack/modules/Gui.h>
#include <dfhack/TileTypes.h>
#include <dfhack/extra/MapExtras.h>
using std::vector;
using std::string;
using namespace DFHack;
DFhackCExport command_result df_grow (Core * c, vector <string> & parameters);
DFhackCExport command_result df_immolate (Core * c, vector <string> & parameters);
DFhackCExport command_result df_extirpate (Core * c, vector <string> & parameters);
DFhackCExport const char * plugin_name ( void )
{
return "plants";
}
DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand> &commands)
{
commands.clear();
commands.push_back(PluginCommand("grow", "Grows saplings into trees (with active cursor, only the targetted one).", df_grow));
commands.push_back(PluginCommand("immolate", "Set plants on fire (under cursor, 'shrubs', 'trees' or 'all').", df_immolate));
commands.push_back(PluginCommand("extirpate", "Kill plants (same mechanics as immolate).", df_extirpate));
return CR_OK;
}
DFhackCExport command_result plugin_shutdown ( Core * c )
{
return CR_OK;
}
enum do_what
{
do_immolate,
do_extirpate
};
static bool getoptions( vector <string> & parameters, bool & shrubs, bool & trees)
{
for(int i = 0;i < parameters.size();i++)
{
if(parameters[i] == "shrubs")
{
shrubs = true;
}
else if(parameters[i] == "trees")
{
trees = true;
}
else if(parameters[i] == "all")
{
trees = true;
shrubs = true;
}
else
{
return false;
}
}
return true;
}
/**
* Book of Immolations, chapter 1, verse 35:
* Armok emerged from the hellish depths and beheld the sunny realms for the first time.
* And he cursed the plants and trees for their bloodless wood, turning them into ash and smoldering ruin.
* Armok was pleased and great temples were built by the dwarves, for they shared his hatred for trees and plants.
*/
static command_result immolations (Core * c, do_what what, bool shrubs, bool trees)
{
c->Suspend();
DFHack::Maps *maps = c->getMaps();
if (!maps->Start())
{
c->con.printerr( "Cannot get map info!\n");
c->Resume();
return CR_FAILURE;
}
DFHack::Gui * Gui = c->getGui();
uint32_t x_max, y_max, z_max;
maps->getSize(x_max, y_max, z_max);
MapExtras::MapCache map(maps);
DFHack::Vegetation *veg = c->getVegetation();
if (!veg->all_plants)
{
std::cerr << "Unable to read vegetation!" << std::endl;
return CR_FAILURE;
}
if(shrubs || trees)
{
int destroyed = 0;
for(size_t i = 0 ; i < veg->all_plants->size(); i++)
{
DFHack::df_plant *p = veg->all_plants->at(i);
if(shrubs && p->is_shrub || trees && !p->is_shrub)
{
if (what == do_immolate)
p->is_burning = true;
p->hitpoints = 0;
destroyed ++;
}
}
c->con.print("Praise Armok!\n");
}
else
{
int32_t x,y,z;
if(Gui->getCursorCoords(x,y,z))
{
vector<DFHack::df_plant *> * alltrees;
if(maps->ReadVegetation(x/16,y/16,z,alltrees))
{
bool didit = false;
for(size_t i = 0 ; i < alltrees->size(); i++)
{
DFHack::df_plant * tree = alltrees->at(i);
if(tree->x == x && tree->y == y && tree->z == z)
{
if(what == do_immolate)
tree->is_burning = true;
tree->hitpoints = 0;
didit = true;
break;
}
}
/*
if(!didit)
{
cout << "----==== There's NOTHING there! ====----" << endl;
}
*/
}
}
else
{
c->con.printerr("No mass destruction and no cursor...\n" );
}
}
// Cleanup
veg->Finish();
maps->Finish();
c->Resume();
return CR_OK;
}
DFhackCExport command_result df_immolate (Core * c, vector <string> & parameters)
{
bool shrubs = false, trees = false;
if(getoptions(parameters,shrubs,trees))
{
return immolations(c,do_immolate,shrubs,trees);
}
else
{
c->con.printerr("Invalid parameter!\n");
return CR_FAILURE;
}
}
DFhackCExport command_result df_extirpate (Core * c, vector <string> & parameters)
{
bool shrubs = false, trees = false;
if(getoptions(parameters,shrubs,trees))
{
return immolations(c,do_extirpate,shrubs,trees);
}
else
{
c->con.printerr("Invalid parameter!\n");
return CR_FAILURE;
}
}
DFhackCExport command_result df_grow (Core * c, vector <string> & parameters)
{
//uint32_t x_max = 0, y_max = 0, z_max = 0;
c->Suspend();
DFHack::Maps *maps = c->getMaps();
Console & con = c->con;
if (!maps->Start())
{
con.printerr("Cannot get map info!\n");
c->Resume();
return CR_FAILURE;
}
//maps->getSize(x_max, y_max, z_max);
MapExtras::MapCache map(maps);
DFHack::Vegetation *veg = c->getVegetation();
if (!veg->all_plants)
{
con.printerr("Unable to read vegetation!\n");
c->Resume();
return CR_FAILURE;
}
DFHack::Gui *Gui = c->getGui();
int32_t x,y,z;
if(Gui->getCursorCoords(x,y,z))
{
vector<DFHack::df_plant *> * alltrees;
if(maps->ReadVegetation(x/16,y/16,z,alltrees))
{
for(size_t i = 0 ; i < alltrees->size(); i++)
{
DFHack::df_plant * tree = alltrees->at(i);
if(tree->x == x && tree->y == y && tree->z == z)
{
if(DFHack::tileShape(map.tiletypeAt(DFHack::DFCoord(x,y,z))) == DFHack::SAPLING_OK)
{
tree->grow_counter = DFHack::sapling_to_tree_threshold;
}
break;
}
}
}
}
else
{
int grown = 0;
for(size_t i = 0 ; i < veg->all_plants->size(); i++)
{
DFHack::df_plant *p = veg->all_plants->at(i);
uint16_t ttype = map.tiletypeAt(DFHack::DFCoord(p->x,p->y,p->z));
if(!p->is_shrub && DFHack::tileShape(ttype) == DFHack::SAPLING_OK)
{
p->grow_counter = DFHack::sapling_to_tree_threshold;
}
}
}
// Cleanup
veg->Finish();
maps->Finish();
c->Resume();
return CR_OK;
}

@ -1 +0,0 @@
dfcleanowned.exe -a

@ -1,2 +0,0 @@
echo | dfprospector.exe -a > dfprospector_report.txt
@dfprospector_report.txt

@ -1 +0,0 @@
dfcleanowned.exe -lx

@ -1,46 +0,0 @@
#include <iostream>
#include <iomanip>
#include <climits>
#include <vector>
#include <sstream>
#include <ctime>
#include <cstdio>
using namespace std;
#include <DFHack.h>
#include <dfhack/VersionInfoFactory.h>
using namespace DFHack;
#include <dfhack/extra/termutil.h>
int main (int numargs, const char ** args)
{
bool temporary_terminal = TemporaryTerminal();
/*
DFHack::VersionInfoFactory * VIF = new DFHack::VersionInfoFactory("Memory.xml");
for(int i = 0; i < VIF->versions.size(); i++)
{
cout << VIF->versions[i]->PrintOffsets();
}
*/
DFHack::ContextManager DFMgr("Memory.xml");
DFHack::Context *DF = DFMgr.getSingleContext();
try
{
DF->Attach();
}
catch (exception& e)
{
cerr << e.what() << endl;
if(temporary_terminal)
cin.ignore();
return 1;
}
cout << DF->getMemoryInfo()->PrintOffsets();
if(temporary_terminal)
{
cout << "Done. Press any key to continue" << endl;
cin.ignore();
}
//delete VIF;
return 0;
}

@ -1,168 +0,0 @@
#include <iostream>
#include <iomanip>
#include <map>
#include <algorithm>
#include <vector>
using namespace std;
#include <DFHack.h>
#include <dfhack/extra/MapExtras.h>
#include <dfhack/extra/termutil.h>
#include <xgetopt.h>
#include <time.h>
#include <stdlib.h>
bool parseOptions(int argc, char **argv,
bool &trees, bool &shrubs, bool &immolate)
{
char c;
xgetopt opt(argc, argv, "sti");
opt.opterr = 0;
while ((c = opt()) != -1)
{
switch (c)
{
case 's':
shrubs = true;
break;
case 't':
trees = true;
break;
case 'i':
immolate = true;
break;
case '?':
switch (opt.optopt)
{
// For when we take arguments
default:
if (isprint(opt.optopt))
std::cerr << "Unknown option -" << opt.optopt << "!"
<< std::endl;
else
std::cerr << "Unknown option character " << (int) opt.optopt << "!"
<< std::endl;
}
default:
// Um.....
return false;
}
}
return true;
}
int main(int argc, char *argv[])
{
bool temporary_terminal = TemporaryTerminal();
bool all_trees = false;
bool all_shrubs = false;
bool immolate = false;
srand(time(0));
if (!parseOptions(argc, argv, all_trees, all_shrubs, immolate))
{
return -1;
}
uint32_t x_max = 0, y_max = 0, z_max = 0;
DFHack::ContextManager manager("Memory.xml");
DFHack::Context *context = manager.getSingleContext();
if (!context->Attach())
{
std::cerr << "Unable to attach to DF!" << std::endl;
if(temporary_terminal)
std::cin.ignore();
return 1;
}
DFHack::Maps *maps = context->getMaps();
if (!maps->Start())
{
std::cerr << "Cannot get map info!" << std::endl;
context->Detach();
if(temporary_terminal)
std::cin.ignore();
return 1;
}
DFHack::Gui * Gui = context->getGui();
maps->getSize(x_max, y_max, z_max);
MapExtras::MapCache map(maps);
uint32_t vegCount = 0;
DFHack::Vegetation *veg = context->getVegetation();
if (!veg->Start(vegCount))
{
std::cerr << "Unable to read vegetation!" << std::endl;
if(temporary_terminal)
cin.ignore();
return 1;
}
if(all_shrubs || all_trees)
{
int destroyed = 0;
for(size_t i = 0 ; i < vegCount; i++)
{
DFHack::dfh_plant p;
veg->Read(i,p);
if(all_shrubs && p.sdata.is_shrub || all_trees && !p.sdata.is_shrub)
{
if (immolate)
p.sdata.is_burning = true;
p.sdata.hitpoints = 0;
veg->Write(p);
destroyed ++;
}
}
cout << "Sacrificed " << destroyed;
if(all_shrubs)
cout << " shrubs to Armok." << endl;
if(all_trees)
cout << " trees to Armok." << endl;
cout << "----==== Praise Armok! ====----" << endl;
}
else
{
int32_t x,y,z;
if(Gui->getCursorCoords(x,y,z))
{
vector<DFHack::dfh_plant> alltrees;
if(maps->ReadVegetation(x/16,y/16,z,&alltrees))
{
bool didit = false;
for(size_t i = 0 ; i < alltrees.size(); i++)
{
DFHack::dfh_plant & tree = alltrees[i];
if(tree.sdata.x == x && tree.sdata.y == y && tree.sdata.z == z)
{
cout << "----==== Praise Armok! ====----" << endl;
if(immolate)
tree.sdata.is_burning = true;
tree.sdata.hitpoints = 0;
veg->Write(tree);
didit = true;
break;
}
}
if(!didit)
{
cout << "----==== There's NOTHING there! ====----" << endl;
}
}
}
else
{
cout << "No mass destruction and no cursor." << endl;
cout << "----==== Armok is not pleased! ====----" << endl;
}
}
// Cleanup
veg->Finish();
maps->Finish();
context->Detach();
if(temporary_terminal)
{
std::cout << " Press any key to finish.";
std::cin.ignore();
}
return 0;
}

@ -1,228 +0,0 @@
// This is a reveal program. It reveals the map.
#include <iostream>
#include <vector>
#include <map>
using namespace std;
#include <DFHack.h>
#include <dfhack/extra/MapExtras.h>
#include <xgetopt.h>
#include <dfhack/modules/Gui.h>
typedef std::vector<DFHack::t_feature*> FeatureListPointer;
typedef std::map<DFHack::DFCoord, FeatureListPointer> FeatureMap;
#ifdef LINUX_BUILD
#include <unistd.h>
void waitmsec (int delay)
{
usleep(delay);
}
#else
#include <windows.h>
void waitmsec (int delay)
{
Sleep(delay);
}
#endif
#include <dfhack/extra/termutil.h>
/*
* Anything that might reveal Hell is unsafe.
*/
bool isSafe(uint32_t x, uint32_t y, uint32_t z, DFHack::Maps *Maps,
MapExtras::MapCache &cache, FeatureMap localFeatures)
{
DFHack::t_feature *blockFeatureLocal = NULL;
DFHack::DFCoord blockCoord(x, y);
MapExtras::Block *b = cache.BlockAt(DFHack::DFCoord(x, y, z));
uint16_t index = b->raw.local_feature;
FeatureMap::const_iterator it = localFeatures.find(blockCoord);
if (it != localFeatures.end())
{
FeatureListPointer features = it->second;
if (index != -1 && index < features.size())
{
blockFeatureLocal = features[index];
}
}
if (blockFeatureLocal == NULL)
return true;
// Adamantine tubes and temples lead to Hell, and Hell *is* Hell.
if (blockFeatureLocal->type != DFHack::feature_Other)
return false;
return true;
}
struct hideblock
{
uint32_t x;
uint32_t y;
uint32_t z;
uint8_t hiddens [16][16];
};
int main (int argc, char *argv[])
{
bool doSafe = false;
char c;
xgetopt opt(argc, argv, "s");
opt.opterr = 0;
while ((c = opt()) != -1)
{
switch (c)
{
case 's':
doSafe = true;
break;
case '?':
switch (opt.optopt)
{
// For when we take arguments
default:
if (isprint(opt.optopt))
std::cerr << "Unknown option -" << opt.optopt << "!"
<< std::endl;
else
std::cerr << "Unknown option character " << (int) opt.optopt << "!"
<< std::endl;
}
default:
// Um.....
return 1;
}
}
bool temporary_terminal = TemporaryTerminal();
uint32_t x_max,y_max,z_max;
DFHack::designations40d designations;
DFHack::ContextManager DFMgr("Memory.xml");
DFHack::Context *DF;
try
{
DF = DFMgr.getSingleContext();
DF->Attach();
}
catch (exception& e)
{
cerr << e.what() << endl;
if(temporary_terminal)
cin.ignore();
return 1;
}
DFHack::Maps *Maps =DF->getMaps();
DFHack::World *World =DF->getWorld();
// walk the map, save the hide bits, reveal.
cout << "Pausing..." << endl;
// horrible hack to make sure the pause is really set
// preblem here is that we could be 'arriving' at the wrong time and DF could be in the middle of a frame.
// that could mean that revealing, even with suspending DF's thread, would mean unleashing hell *in the same frame*
// this here hack sets the pause state, resumes DF, waits a second for it to enter the pause (I know, BS value.) and suspends.
World->SetPauseState(true);
DF->Resume();
waitmsec(1000);
DF->Suspend();
cout << "Revealing, please wait..." << endl;
// init the map
if(!Maps->Start())
{
cerr << "Can't init map." << endl;
if(temporary_terminal)
cin.ignore();
return 1;
}
MapExtras::MapCache cache(Maps);
FeatureMap localFeatures;
if(doSafe && !Maps->ReadLocalFeatures(localFeatures))
{
std::cerr << "Unable to read local features; can't reveal map "
<< "safely" << std::endl;
if(temporary_terminal)
cin.ignore();
return 1;
}
Maps->getSize(x_max,y_max,z_max);
vector <hideblock> hidesaved;
// We go from the top z-level down, stopping as soon as we encounter
// something that might lead to Hell, so the player can unpause without
// spawning demons.
bool quit = false;
for(uint32_t z = z_max - 1; z > 0 && !quit;z--)
{
for(uint32_t y = 0; y < y_max;y++)
{
for(uint32_t x = 0; x < x_max;x++)
{
if(Maps->isValidBlock(x,y,z))
{
if (doSafe && !isSafe(x, y, z, Maps, cache, localFeatures))
quit = true;
hideblock hb;
hb.x = x;
hb.y = y;
hb.z = z;
// read block designations
Maps->ReadDesignations(x,y,z, &designations);
// change the hidden flag to 0
for (uint32_t i = 0; i < 16;i++) for (uint32_t j = 0; j < 16;j++)
{
hb.hiddens[i][j] = designations[i][j].bits.hidden;
designations[i][j].bits.hidden = 0;
}
hidesaved.push_back(hb);
// write the designations back
Maps->WriteDesignations(x,y,z, &designations);
}
}
}
}
// FIXME: force game pause here!
DF->Detach();
cout << "Map revealed. The game has been paused for you." << endl;
if (doSafe)
cout << "Unpausing *WON'T* reveal hell." << endl << endl;
else
cout << "Unpausing can unleash the forces of hell!" << endl << endl;
cout << "Press any key to unreveal." << endl;
cout << "Close to keep the map revealed !!FOREVER!!" << endl;
cin.ignore();
cout << "Unrevealing... please wait." << endl;
// FIXME: do some consistency checks here!
DF->Attach();
Maps = DF->getMaps();
Maps->Start();
for(size_t i = 0; i < hidesaved.size();i++)
{
hideblock & hb = hidesaved[i];
Maps->ReadDesignations(hb.x,hb.y,hb.z, &designations);
for (uint32_t i = 0; i < 16;i++) for (uint32_t j = 0; j < 16;j++)
{
designations[i][j].bits.hidden = hb.hiddens[i][j];
}
Maps->WriteDesignations(hb.x,hb.y,hb.z, &designations);
}
if(temporary_terminal)
{
cout << "Done. Press any key to continue" << endl;
cin.ignore();
}
return 0;
}