outsideOnly: allow checking periodically in case a building was made outside and then became inside.

develop
expwnent 2014-06-20 19:48:56 -04:00
parent c0e6e62cea
commit f94fc5846d
1 changed files with 66 additions and 5 deletions

@ -30,8 +30,10 @@ static map<std::string, int32_t> registeredBuildings;
const int32_t OUTSIDE_ONLY = 1; const int32_t OUTSIDE_ONLY = 1;
const int32_t EITHER = 0; const int32_t EITHER = 0;
const int32_t INSIDE_ONLY = -1; const int32_t INSIDE_ONLY = -1;
int32_t checkEvery = -1;
void buildingCreated(color_ostream& out, void* data); void buildingCreated(color_ostream& out, void* data);
void checkBuildings(color_ostream& out, void* data);
command_result outsideOnly(color_ostream& out, vector<string>& parameters); command_result outsideOnly(color_ostream& out, vector<string>& parameters);
DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands) DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
@ -44,6 +46,8 @@ DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <Plug
" registers [custom building name] as inside-only\n" " registers [custom building name] as inside-only\n"
" outsideOnly either [custom building name]\n" " outsideOnly either [custom building name]\n"
" unregisters [custom building name]\n" " unregisters [custom building name]\n"
" outsideOnly checkEvery [n]\n"
" checks for buildings that were previously in appropriate inside/outsideness but are not anymore every [n] ticks. If [n] is negative, disables checking.\n"
" outsideOnly clear\n" " outsideOnly clear\n"
" unregisters all custom buildings\n" " unregisters all custom buildings\n"
" enable outsideOnly\n" " enable outsideOnly\n"
@ -63,7 +67,7 @@ DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <Plug
DFhackCExport command_result plugin_onstatechange(color_ostream &out, state_change_event event) DFhackCExport command_result plugin_onstatechange(color_ostream &out, state_change_event event)
{ {
switch (event) { switch (event) {
case SC_GAME_UNLOADED: case SC_WORLD_UNLOADED:
registeredBuildings.clear(); registeredBuildings.clear();
break; break;
default: default:
@ -76,14 +80,61 @@ DFhackCExport command_result plugin_enable(color_ostream& out, bool enable) {
if ( enabled == enable ) if ( enabled == enable )
return CR_OK; return CR_OK;
enabled = enable; enabled = enable;
EventManager::unregisterAll(plugin_self);
if ( enabled ) { if ( enabled ) {
EventManager::EventHandler handler(buildingCreated,1); EventManager::EventHandler handler(buildingCreated,1);
EventManager::registerListener(EventManager::EventType::BUILDING, handler, plugin_self); EventManager::registerListener(EventManager::EventType::BUILDING, handler, plugin_self);
checkBuildings(out, 0);
}
return CR_OK;
}
void destroy(df::building* building) {
if ( Buildings::deconstruct(building) )
return;
building->flags.bits.almost_deleted = 1;
}
void checkBuildings(color_ostream& out, void* data) {
if ( !enabled )
return;
std::vector<df::building*>& buildings = df::global::world->buildings.all;
for ( size_t a = 0; a < buildings.size(); a++ ) {
df::building* building = buildings[a];
if ( building == NULL )
continue;
if ( building->getCustomType() < 0 )
continue;
df::coord pos(building->centerx,building->centery,building->z);
df::tile_designation* des = Maps::getTileDesignation(pos);
bool outside = des->bits.outside;
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 )
continue;
destroy(building);
} else if ( type == INSIDE_ONLY ) {
if ( !outside )
continue;
destroy(building);
} else { } else {
EventManager::unregisterAll(plugin_self); if ( DFHack::Once::doOnce("outsideOnly invalid setting") ) {
out.print("Error: outsideOnly: building has invalid setting: %s %d\n", def->code.c_str(), type);
}
} }
} }
if ( checkEvery < 0 )
return;
EventManager::EventHandler timeHandler(checkBuildings,-1);
EventManager::registerTick(timeHandler, checkEvery, plugin_self);
}
command_result outsideOnly(color_ostream& out, vector<string>& parameters) { command_result outsideOnly(color_ostream& out, vector<string>& parameters) {
int32_t status = 2; int32_t status = 2;
for ( size_t a = 0; a < parameters.size(); a++ ) { for ( size_t a = 0; a < parameters.size(); a++ ) {
@ -95,15 +146,25 @@ command_result outsideOnly(color_ostream& out, vector<string>& parameters) {
status = INSIDE_ONLY; status = INSIDE_ONLY;
} else if ( parameters[a] == "either" ) { } else if ( parameters[a] == "either" ) {
status = EITHER; status = EITHER;
} else { } else if ( parameters[a] == "checkEvery" ) {
if (a+1 >= parameters.size()) {
out.printerr("You must specify how often to check.\n");
return CR_WRONG_USAGE;
}
checkEvery = atoi(parameters[a].c_str());
}
else {
if ( status == 2 ) { if ( status == 2 ) {
out.print("Error: you need to tell outsideOnly whether the building is inside only, outside-only or either.\n"); out.printerr("Error: you need to tell outsideOnly whether the building is inside only, outside-only or either.\n");
return CR_WRONG_USAGE; return CR_WRONG_USAGE;
} }
registeredBuildings[parameters[a]] = status; registeredBuildings[parameters[a]] = status;
} }
} }
out.print("outsideOnly is %s\n", enabled ? "enabled" : "disabled"); out.print("outsideOnly is %s\n", enabled ? "enabled" : "disabled");
if ( enabled ) {
}
return CR_OK; return CR_OK;
} }