outsideOnly: registration of buildings is now required, and you can also register buildings as inside-only.

develop
expwnent 2014-06-20 18:49:11 -04:00
parent b031229de7
commit c0e6e62cea
3 changed files with 101 additions and 17 deletions

@ -1,6 +1,12 @@
DFHack future
The future has not yet happened. Stay tuned!
Internals:
New scripts:
New commands:
New tweaks:
New plugins:
Misc improvements:
- outsideOnly: now buildings have to be registered as inside or outside only
DFHack v0.34.11-r5

@ -954,7 +954,7 @@ Again, note that plugins AND scripts can be executed this way, and arguments wil
outsideOnly
-----------
This plugin makes it so that buildings whose names begin with ``OUTSIDE_ONLY`` cannot be built inside. If the player attempts to do so, the building will automatically be deconstructed.
This plugin makes custom buildings either inside-only or outside-only. If you attempt to build one in an inappropriate location, the building plan will immediately deconstruct. Try `help outsideOnly` for details.
syndromeTrigger
---------------

@ -8,6 +8,7 @@
#include "modules/Buildings.h"
#include "modules/EventManager.h"
#include "modules/Maps.h"
#include "modules/Once.h"
#include "df/coord.h"
#include "df/building.h"
@ -15,25 +16,94 @@
#include "df/map_block.h"
#include "df/tile_designation.h"
#include <map>
#include <string>
//TODO: check if building becomes inside/outside later
using namespace DFHack;
using namespace std;
DFHACK_PLUGIN_IS_ENABLED(enabled);
DFHACK_PLUGIN("outsideOnly");
static map<std::string, int32_t> registeredBuildings;
const int32_t OUTSIDE_ONLY = 1;
const int32_t EITHER = 0;
const int32_t INSIDE_ONLY = -1;
void buildingCreated(color_ostream& out, void* data);
command_result outsideOnly(color_ostream& out, vector<string>& parameters);
DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
{
EventManager::EventHandler handler(buildingCreated,1);
EventManager::registerListener(EventManager::EventType::BUILDING, handler, plugin_self);
commands.push_back(PluginCommand("outsideOnly", "Register buildings as inside/outside only. If the player attempts to construct them in an inapproprate place, the building plan automatically deconstructs.\n", &outsideOnly, false,
"outsideOnly:\n"
" outsideOnly outside [custom building name]\n"
" registers [custom building name] as outside-only\n"
" outsideOnly inside [custom building name]\n"
" registers [custom building name] as inside-only\n"
" outsideOnly either [custom building name]\n"
" unregisters [custom building name]\n"
" outsideOnly clear\n"
" unregisters all custom buildings\n"
" enable outsideOnly\n"
" enables the plugin. Plugin must be enabled to function!\n"
" disable outsideOnly\n"
" disables the plugin\n"
" outsideOnly clear outside BUILDING_1 BUILDING_2 inside BUILDING_3\n"
" equivalent to:\n"
" outsideOnly clear\n"
" outsideOnly outside BUILDING_1\n"
" outsideOnly outside BUILDING_2\n"
" outsideOnly inside BUILDING_3\n"
));
return CR_OK;
}
// This is called right before the plugin library is removed from memory.
DFhackCExport command_result plugin_shutdown ( color_ostream &out )
DFhackCExport command_result plugin_onstatechange(color_ostream &out, state_change_event event)
{
switch (event) {
case SC_GAME_UNLOADED:
registeredBuildings.clear();
break;
default:
break;
}
return CR_OK;
}
DFhackCExport command_result plugin_enable(color_ostream& out, bool enable) {
if ( enabled == enable )
return CR_OK;
enabled = enable;
if ( enabled ) {
EventManager::EventHandler handler(buildingCreated,1);
EventManager::registerListener(EventManager::EventType::BUILDING, handler, plugin_self);
} else {
EventManager::unregisterAll(plugin_self);
}
}
command_result outsideOnly(color_ostream& out, vector<string>& parameters) {
int32_t status = 2;
for ( size_t a = 0; a < parameters.size(); a++ ) {
if ( parameters[a] == "clear" ) {
registeredBuildings.clear();
} else if ( parameters[a] == "outside" ) {
status = OUTSIDE_ONLY;
} else if ( parameters[a] == "inside" ) {
status = INSIDE_ONLY;
} else if ( parameters[a] == "either" ) {
status = EITHER;
} else {
if ( status == 2 ) {
out.print("Error: you need to tell outsideOnly whether the building is inside only, outside-only or either.\n");
return CR_WRONG_USAGE;
}
registeredBuildings[parameters[a]] = status;
}
}
out.print("outsideOnly is %s\n", enabled ? "enabled" : "disabled");
return CR_OK;
}
@ -45,19 +115,27 @@ void buildingCreated(color_ostream& out, void* data) {
if ( building->getCustomType() < 0 )
return;
string prefix("OUTSIDE_ONLY");
df::building_def* def = df::global::world->raws.buildings.all[building->getCustomType()];
if (def->code.compare(0, prefix.size(), prefix)) {
return;
}
//now, just check if it was created inside, and if so, scuttle it
//check if it was created inside or outside
df::coord pos(building->centerx,building->centery,building->z);
df::tile_designation* des = Maps::getTileDesignation(pos);
if ( des->bits.outside )
return;
bool outside = des->bits.outside;
Buildings::deconstruct(building);
df::building_def* def = df::global::world->raws.buildings.all[building->getCustomType()];
int32_t type = registeredBuildings[def->code];
if ( type == EITHER ) {
registeredBuildings.erase(def->code);
} else if ( type == OUTSIDE_ONLY ) {
if ( outside )
return;
Buildings::deconstruct(building);
} else if ( type == INSIDE_ONLY ) {
if ( !outside )
return;
Buildings::deconstruct(building);
} else {
if ( DFHack::Once::doOnce("outsideOnly invalid setting") ) {
out.print("Error: outsideOnly: building has invalid setting: %s %d\n", def->code.c_str(), type);
}
}
}