Vermin module and colonies plugin
This is the start of the vermin module. Right now it just gets a list of the positions at which vermin are created (spawn points). Most spawn points are invisible and transient, but colonies (ant hills and such) are permanent and visible. The address of the spawn points vector is only provided for Linux 0.31.25 The colonies plugin uses the vermin module to list the location and species of colonies, and can either wipe them all out or turn them all into honey bee colonies.develop
parent
1b011cdf6c
commit
d1170d54c3
@ -0,0 +1,86 @@
|
||||
#pragma once
|
||||
#ifndef CL_MOD_VERMIN
|
||||
#define CL_MOD_VERMIN
|
||||
/**
|
||||
* \defgroup grp_vermin Wild vermin (ants, bees, etc)
|
||||
* @ingroup grp_vermin
|
||||
*/
|
||||
#include "dfhack/Export.h"
|
||||
#include "dfhack/Module.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
namespace DFHack
|
||||
{
|
||||
#endif
|
||||
/**
|
||||
* Structure for holding a read DF vermin spawn point object
|
||||
* \ingroup grp_vermin
|
||||
*/
|
||||
struct t_spawnPoint
|
||||
{
|
||||
uint32_t origin;
|
||||
uint16_t race;
|
||||
uint16_t type;
|
||||
uint16_t x;
|
||||
uint16_t y;
|
||||
uint16_t z;
|
||||
bool in_use;
|
||||
uint8_t unknown;
|
||||
uint32_t countdown;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
class DFContextShared;
|
||||
class SpawnPoints;
|
||||
|
||||
/**
|
||||
* The Vermin module - allows reading DF vermin
|
||||
* \ingroup grp_modules
|
||||
* \ingroup grp_vermin
|
||||
*/
|
||||
class DFHACK_EXPORT Vermin : public Module
|
||||
{
|
||||
public:
|
||||
Vermin();
|
||||
~Vermin();
|
||||
|
||||
bool Finish();
|
||||
|
||||
// NOTE: caller must call delete on result when done.
|
||||
SpawnPoints* getSpawnPoints();
|
||||
|
||||
private:
|
||||
struct Private;
|
||||
Private *d;
|
||||
|
||||
friend class SpawnPoints;
|
||||
};
|
||||
|
||||
class DFHACK_EXPORT SpawnPoints
|
||||
{
|
||||
public:
|
||||
static const uint16_t TYPE_WILD_COLONY = 0xFFFF;
|
||||
|
||||
protected:
|
||||
SpawnPoints(Vermin * v);
|
||||
|
||||
public:
|
||||
~SpawnPoints();
|
||||
|
||||
size_t size();
|
||||
bool Read (const uint32_t index, t_spawnPoint & point);
|
||||
bool Write (const uint32_t index, t_spawnPoint & point);
|
||||
bool isValid();
|
||||
|
||||
static bool isWildColony(t_spawnPoint & point);
|
||||
|
||||
private:
|
||||
Vermin* v;
|
||||
std::vector <void*> * p_sp;
|
||||
|
||||
friend class Vermin;
|
||||
};
|
||||
}
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif
|
@ -0,0 +1,191 @@
|
||||
/*
|
||||
www.sourceforge.net/projects/dfhack
|
||||
Copyright (c) 2009 Petr Mrázek (peterix), Kenneth Ferland (Impaler[WrG]), dorf
|
||||
|
||||
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>
|
||||
using namespace std;
|
||||
|
||||
#include "dfhack/VersionInfo.h"
|
||||
#include "dfhack/Types.h"
|
||||
#include "dfhack/Error.h"
|
||||
#include "dfhack/Process.h"
|
||||
#include "dfhack/modules/Vermin.h"
|
||||
#include "ModuleFactory.h"
|
||||
#include "dfhack/Core.h"
|
||||
using namespace DFHack;
|
||||
|
||||
struct Vermin::Private
|
||||
{
|
||||
uint32_t spawn_points_vector;
|
||||
uint32_t race_offset;
|
||||
uint32_t type_offset;
|
||||
uint32_t position_offset;
|
||||
uint32_t in_use_offset;
|
||||
uint32_t unknown_offset;
|
||||
uint32_t countdown_offset;
|
||||
Process * owner;
|
||||
bool Inited;
|
||||
bool Started;
|
||||
};
|
||||
|
||||
Module* DFHack::createVermin()
|
||||
{
|
||||
return new Vermin();
|
||||
}
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
Vermin::Vermin()
|
||||
{
|
||||
Core & c = Core::getInstance();
|
||||
|
||||
d = new Private;
|
||||
d->owner = c.p;
|
||||
d->Inited = d->Started = false;
|
||||
VersionInfo * mem = c.vinfo;
|
||||
OffsetGroup * OG_vermin = mem->getGroup("Vermin");
|
||||
OffsetGroup * OG_spawn = OG_vermin->getGroup("Spawn Points");
|
||||
d->Inited = true;
|
||||
try
|
||||
{
|
||||
d->spawn_points_vector = OG_spawn->getAddress("vector");
|
||||
|
||||
d->race_offset = OG_spawn->getOffset("race");
|
||||
d->type_offset = OG_spawn->getOffset("type");
|
||||
d->position_offset = OG_spawn->getOffset("position");
|
||||
d->in_use_offset = OG_spawn->getOffset("in_use");
|
||||
d->unknown_offset = OG_spawn->getOffset("unknown");
|
||||
d->countdown_offset = OG_spawn->getOffset("countdown");
|
||||
}
|
||||
catch(DFHack::Error::AllMemdef &e)
|
||||
{
|
||||
cerr << "Vermin not available... " << e.what() << endl;
|
||||
d->Inited = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool Vermin::Finish()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
Vermin::~Vermin()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
// NOTE: caller must call delete on result when done.
|
||||
SpawnPoints* Vermin::getSpawnPoints()
|
||||
{
|
||||
if (!d->Inited)
|
||||
{
|
||||
cerr << "Couldn't get spawn points: Vermin module not inited" << endl;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return new SpawnPoints(this);
|
||||
}
|
||||
|
||||
SpawnPoints::SpawnPoints(Vermin* v_)
|
||||
{
|
||||
v = v_;
|
||||
p_sp = NULL;
|
||||
|
||||
if (!v->d->Inited)
|
||||
{
|
||||
cerr << "Couldn't get spawn points: Vermin module not inited" << endl;
|
||||
return;
|
||||
}
|
||||
|
||||
//p_sp = new DfVector <uint32_t> (v->d->spawn_points_vector);
|
||||
//p_sp = new vector <void*> (v->d->spawn_points_vector);
|
||||
p_sp = (vector <void*>*) (v->d->spawn_points_vector);
|
||||
}
|
||||
|
||||
SpawnPoints::~SpawnPoints()
|
||||
{
|
||||
// Do NOT delete p_sp; it's a pointer to memory the game owns.
|
||||
}
|
||||
|
||||
size_t SpawnPoints::size()
|
||||
{
|
||||
if (!isValid())
|
||||
return 0;
|
||||
|
||||
return p_sp->size();
|
||||
}
|
||||
|
||||
bool SpawnPoints::Read (const uint32_t index, t_spawnPoint & sp)
|
||||
{
|
||||
if(!isValid())
|
||||
return false;
|
||||
|
||||
// read pointer from vector at position
|
||||
uint32_t temp = (uint32_t) p_sp->at (index);
|
||||
|
||||
sp.origin = temp;
|
||||
sp.race = v->d->owner->readWord(temp + v->d->race_offset);
|
||||
sp.type = v->d->owner->readWord(temp + v->d->type_offset);
|
||||
sp.in_use = v->d->owner->readByte(temp + v->d->in_use_offset);
|
||||
sp.unknown = v->d->owner->readByte(temp + v->d->unknown_offset);
|
||||
sp.countdown = v->d->owner->readDWord(temp + v->d->countdown_offset);
|
||||
|
||||
// Three consecutive 16 bit numbers for x/y/z
|
||||
v->d->owner->read(temp + v->d->position_offset, 6, (uint8_t*) &sp.x);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SpawnPoints::Write (const uint32_t index, t_spawnPoint & sp)
|
||||
{
|
||||
if(!isValid())
|
||||
return false;
|
||||
|
||||
// read pointer from vector at position
|
||||
uint32_t temp = (uint32_t) p_sp->at (index);
|
||||
|
||||
v->d->owner->writeWord(temp + v->d->race_offset, sp.race);
|
||||
v->d->owner->writeWord(temp + v->d->type_offset, sp.type);
|
||||
v->d->owner->writeByte(temp + v->d->in_use_offset, sp.in_use);
|
||||
v->d->owner->writeByte(temp + v->d->unknown_offset, sp.unknown);
|
||||
v->d->owner->writeDWord(temp + v->d->countdown_offset, sp.countdown);
|
||||
|
||||
// Three consecutive 16 bit numbers for x/y/z
|
||||
v->d->owner->write(temp + v->d->position_offset, 6, (uint8_t*) &sp.x);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SpawnPoints::isWildColony(t_spawnPoint & point)
|
||||
{
|
||||
return (point.type == TYPE_WILD_COLONY);
|
||||
}
|
||||
|
||||
bool SpawnPoints::isValid()
|
||||
{
|
||||
return (v != NULL && v->d->Inited && p_sp != NULL);
|
||||
}
|
@ -0,0 +1,163 @@
|
||||
#include <dfhack/Core.h>
|
||||
#include <dfhack/Console.h>
|
||||
#include <dfhack/Export.h>
|
||||
#include <dfhack/PluginManager.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <dfhack/modules/Vermin.h>
|
||||
|
||||
using std::vector;
|
||||
using std::string;
|
||||
using namespace DFHack;
|
||||
#include <DFHack.h>
|
||||
|
||||
DFhackCExport command_result colonies (Core * c, vector <string> & parameters);
|
||||
|
||||
DFhackCExport const char * plugin_name ( void )
|
||||
{
|
||||
return "colonies";
|
||||
}
|
||||
|
||||
DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand> &commands)
|
||||
{
|
||||
commands.clear();
|
||||
commands.push_back(PluginCommand("colonies",
|
||||
"List or change wild colonies (ants hills and such)\
|
||||
\n Options: 'kill' = destroy all colonies\
|
||||
\n 'bees' = change all colonies to honey bees",
|
||||
colonies));
|
||||
return CR_OK;
|
||||
}
|
||||
|
||||
DFhackCExport command_result plugin_shutdown ( Core * c )
|
||||
{
|
||||
return CR_OK;
|
||||
}
|
||||
|
||||
void destroyColonies(DFHack::SpawnPoints *points);
|
||||
void convertColonies(DFHack::SpawnPoints *points, DFHack::Materials *Materials);
|
||||
void showColonies(DFHack::SpawnPoints *points, DFHack::Materials *Materials);
|
||||
|
||||
DFhackCExport command_result colonies (Core * c, vector <string> & parameters)
|
||||
{
|
||||
bool destroy = false;
|
||||
bool convert = false;
|
||||
|
||||
for(int i = 0; i < parameters.size();i++)
|
||||
{
|
||||
if(parameters[i] == "kill")
|
||||
destroy = true;
|
||||
else if(parameters[i] == "bees")
|
||||
convert = true;
|
||||
}
|
||||
|
||||
if (destroy && convert)
|
||||
{
|
||||
|
||||
dfout << "Kill or make bees? DECIDE!" << std::endl;
|
||||
return CR_FAILURE;
|
||||
}
|
||||
|
||||
c->Suspend();
|
||||
|
||||
Vermin * vermin = c->getVermin();
|
||||
Materials * materials = c->getMaterials();
|
||||
|
||||
SpawnPoints *points = vermin->getSpawnPoints();
|
||||
|
||||
if(!points->isValid())
|
||||
{
|
||||
std::cerr << "vermin not supported for this DF version" << std::endl;
|
||||
return CR_FAILURE;
|
||||
}
|
||||
|
||||
materials->ReadCreatureTypesEx();
|
||||
|
||||
if (destroy)
|
||||
destroyColonies(points);
|
||||
else if (convert)
|
||||
convertColonies(points, materials);
|
||||
else
|
||||
showColonies(points, materials);
|
||||
|
||||
delete points;
|
||||
|
||||
vermin->Finish();
|
||||
materials->Finish();
|
||||
|
||||
c->Resume();
|
||||
return CR_OK;
|
||||
}
|
||||
|
||||
void destroyColonies(DFHack::SpawnPoints *points)
|
||||
{
|
||||
uint32_t numSpawnPoints = points->size();
|
||||
for (uint32_t i = 0; i < numSpawnPoints; i++)
|
||||
{
|
||||
DFHack::t_spawnPoint sp;
|
||||
points->Read(i, sp);
|
||||
|
||||
if (sp.in_use && DFHack::SpawnPoints::isWildColony(sp))
|
||||
{
|
||||
sp.in_use = false;
|
||||
points->Write(i, sp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Convert all colonies to honey bees.
|
||||
void convertColonies(DFHack::SpawnPoints *points, DFHack::Materials *Materials)
|
||||
{
|
||||
int bee_idx = -1;
|
||||
for (size_t i = 0; i < Materials->raceEx.size(); i++)
|
||||
if (strcmp(Materials->raceEx[i].rawname, "HONEY_BEE") == 0)
|
||||
{
|
||||
bee_idx = i;
|
||||
break;
|
||||
}
|
||||
|
||||
if (bee_idx == -1)
|
||||
{
|
||||
std::cerr << "Honey bees not present in game." << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t numSpawnPoints = points->size();
|
||||
for (uint32_t i = 0; i < numSpawnPoints; i++)
|
||||
{
|
||||
DFHack::t_spawnPoint sp;
|
||||
points->Read(i, sp);
|
||||
|
||||
if (sp.in_use && DFHack::SpawnPoints::isWildColony(sp))
|
||||
{
|
||||
sp.race = bee_idx;
|
||||
points->Write(i, sp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void showColonies(DFHack::SpawnPoints *points, DFHack::Materials *Materials)
|
||||
{
|
||||
uint32_t numSpawnPoints = points->size();
|
||||
int numColonies = 0;
|
||||
for (uint32_t i = 0; i < numSpawnPoints; i++)
|
||||
{
|
||||
DFHack::t_spawnPoint sp;
|
||||
|
||||
points->Read(i, sp);
|
||||
|
||||
if (sp.in_use && DFHack::SpawnPoints::isWildColony(sp))
|
||||
{
|
||||
numColonies++;
|
||||
string race="(no race)";
|
||||
if (Materials->raceEx[sp.race].rawname[0])
|
||||
race = Materials->raceEx[sp.race].rawname;
|
||||
|
||||
fprintf(dfout_C, "Spawn point %u: %s at %d:%d:%d\n",
|
||||
i, race.c_str(), sp.x, sp.y, sp.z);
|
||||
}
|
||||
}
|
||||
|
||||
if (numColonies == 0)
|
||||
dfout << "No colonies present." << std::endl;
|
||||
}
|
Loading…
Reference in New Issue