Petr Mrázek 2012-04-15 00:12:38 +02:00
commit c52eb517b0
3 changed files with 70 additions and 44 deletions

@ -615,8 +615,7 @@ Options
-------
:tweak clear-missing: Remove the missing status from the selected unit. This allows engraving slabs for ghostly, but not yet found, creatures.
:tweak clear-ghostly: Remove the ghostly status from the selected unit and mark it as dead. This allows getting rid of bugged ghosts which do not show up in the engraving slab menu at all, even after using clear-missing. It works, but is potentially very dangerous - so use with care. Probably (almost certainly) it does not have the same effects like a proper burial. You've been warned.
:tweak clear-resident: Remove the resident flag from the selected unit. Intended to fix bugged migrants who stay at the map edge and don't enter your fort. Only works for dwarves of the own civilization.
:tweak clear-merchant: Remove the merchant flag from the selected unit. Assimilates bugged merchants who don't leave the map into your fort. Only works for dwarves of the own civilization.
:tweak fixmigrant: Remove the resident/merchant flag from the selected unit. Intended to fix bugged migrants/traders who stay at the map edge and don't enter your fort. Only works for dwarves (or generally the player's race in modded games). Can be abused to grab caravan merchants, but that might result into weirdness during trading.
tubefill
========

@ -10,6 +10,8 @@
#include "modules/Units.h"
#include "modules/Items.h"
#include "MiscUtils.h"
#include "DataDefs.h"
#include "df/ui.h"
#include "df/world.h"
@ -53,14 +55,11 @@ DFhackCExport command_result plugin_init (color_ostream &out, std::vector <Plugi
" Intended to fix the case where you can't engrave memorials for ghosts.\n"
" Note that this is very dirty and possibly dangerous!\n"
" Most probably does not have the positive effect of a proper burial.\n"
" tweak clear-resident\n"
" Remove the resident flag from the selected unit.\n"
" Intended to fix bugged migrants who stay at the map edge.\n"
" Only works for dwarves of the own civilization.\n"
" tweak clear-merchant\n"
" Remove the merchant flag from the selected unit.\n"
" Assimilates bugged merchants who don't leave the map into your fort.\n"
" Only works for dwarves of the own civilization.\n"
" tweak fixmigrant\n"
" Forces the selected unit to become a member or your fortress.\n"
" Intended to fix bugged migrants and merchants who stay at the map edge.\n"
" Only works for units of your own race. Can be used for stealing caravan\n"
" traders and guards, but might result into weirdness during trading.\n"
));
return CR_OK;
}
@ -73,9 +72,10 @@ DFhackCExport command_result plugin_shutdown (color_ostream &out)
static command_result lair(color_ostream &out, std::vector<std::string> & params);
// to be called by tweak-merchant and tweak-resident
// to be called by tweak-fixmigrant
// units forced into the fort by removing the flags do not own their clothes
// which has the result that they drop all their clothes and become unhappy because they are naked
// so we need to make them own their clothes and add them to their uniform
command_result fix_clothing_ownership(color_ostream &out, df::unit* unit)
{
// first, find one owned item to initialize the vtable
@ -101,6 +101,8 @@ command_result fix_clothing_ownership(color_ostream &out, df::unit* unit)
{
df::unit_inventory_item* inv_item = unit->inventory[j];
df::item* item = inv_item->item;
// unforbid items (for the case of kidnapping caravan escorts who have their stuff forbidden by default)
inv_item->item->flags.bits.forbid = 0;
if(inv_item->mode == df::unit_inventory_item::T_mode::Worn)
{
// ignore armor?
@ -111,12 +113,18 @@ command_result fix_clothing_ownership(color_ostream &out, df::unit* unit)
if(!Items::getOwner(item))
{
if(Items::setOwner(item, unit))
{
// add to uniform, so they know they should wear their clothes
insert_into_vector(unit->military.uniforms[0], item->id);
fixcount++;
}
else
out << "could not change ownership for item!" << endl;
}
}
}
// clear uniform_drop (without this they would drop their clothes and pick them up some time later)
unit->military.uniform_drop.clear();
out << "ownership for " << fixcount << " clothes fixed" << endl;
return CR_OK;
}
@ -166,49 +174,67 @@ static command_result tweak(color_ostream &out, vector <string> &parameters)
return CR_FAILURE;
}
}
else if (cmd == "clear-resident")
else if (cmd == "fixmigrant")
{
df::unit *unit = getSelectedUnit(out);
if (!unit)
return CR_FAILURE;
// must be own race and civ and a merchant
if ( unit->flags2.bits.resident
&& unit->race == df::global::ui->race_id
&& unit->civ_id == df::global::ui->civ_id)
if (!unit)
{
// remove resident flag
unit->flags2.bits.resident = 0;
return fix_clothing_ownership(out, unit);
out << "No unit selected!" << endl;
return CR_FAILURE;
}
else
if(unit->race != df::global::ui->race_id)
{
out.print("That's not a resident dwarf of your civilization!\n");
out << "Selected unit does not belong to your race!" << endl;
return CR_FAILURE;
}
// case #1: migrants who have the resident flag set
// see http://dffd.wimbli.com/file.php?id=6139 for a save
if (unit->flags2.bits.resident)
unit->flags2.bits.resident = 0;
// case #2: migrants who have the merchant flag
// happens on almost all maps after a few migrant waves
if(unit->flags1.bits.merchant)
unit->flags1.bits.merchant = 0;
// this one is a cheat, but bugged migrants usually have the same civ_id
// so it should not be triggered in most cases
// if it happens that the player has 'foreign' units of the same race
// (vanilla df: dwarves not from mountainhome) on his map, just grab them
if(unit->civ_id != df::global::ui->civ_id)
unit->civ_id = df::global::ui->civ_id;
return fix_clothing_ownership(out, unit);
}
else if (cmd == "clear-merchant")
else if (cmd == "makeown")
{
// force a unit into your fort, regardless of civ or race
// allows to "steal" caravan guards etc
df::unit *unit = getSelectedUnit(out);
if (!unit)
return CR_FAILURE;
// must be own race and civ and a merchant
if ( unit->flags1.bits.merchant
&& unit->race == df::global::ui->race_id
&& unit->civ_id == df::global::ui->civ_id)
{
// remove merchant flag
unit->flags1.bits.merchant = 0;
return fix_clothing_ownership(out, unit);
}
else
{
out.print("That's not a dwarf merchant of your civilization!\n");
out << "No unit selected!" << endl;
return CR_FAILURE;
}
if (unit->flags2.bits.resident)
unit->flags2.bits.resident = 0;
if(unit->flags1.bits.merchant)
unit->flags1.bits.merchant = 0;
if(unit->flags1.bits.forest)
unit->flags1.bits.forest = 0;
if(unit->civ_id != df::global::ui->civ_id)
unit->civ_id = df::global::ui->civ_id;
if(unit->profession == df::profession::MERCHANT)
unit->profession = df::profession::TRADER;
if(unit->profession2 == df::profession::MERCHANT)
unit->profession2 = df::profession::TRADER;
return fix_clothing_ownership(out, unit);
}
else return CR_WRONG_USAGE;
else
return CR_WRONG_USAGE;
return CR_OK;
}

@ -905,7 +905,7 @@ bool isAssigned(df::unit* unit)
if( rtype == df::general_ref_type::BUILDING_CIVZONE_ASSIGNED
|| rtype == df::general_ref_type::BUILDING_CAGED
|| rtype == df::general_ref_type::BUILDING_CHAIN
|| (rtype == df::general_ref_type::CONTAINED_IN_ITEM && isBuiltCageAtPos(unit->pos))
|| (rtype == df::general_ref_type::CONTAINED_IN_ITEM && isInBuiltCage(unit))
)
{
assigned = true;
@ -958,12 +958,11 @@ bool isInBuiltCage(df::unit* unit)
df::building* building = world->buildings.all[b];
if( building->getType() == building_type::Cage)
{
df::building_cagest* oldcage = (df::building_cagest*) building;
for(size_t oc=0; oc<oldcage->assigned_creature.size(); oc++)
df::building_cagest* cage = (df::building_cagest*) building;
for(size_t c=0; c<cage->assigned_creature.size(); c++)
{
if(oldcage->assigned_creature[oc] == unit->id)
if(cage->assigned_creature[c] == unit->id)
{
oldcage->assigned_creature.erase(oldcage->assigned_creature.begin() + oc);
caged = true;
break;
}
@ -2770,7 +2769,9 @@ command_result autoButcher( color_ostream &out, bool verbose = false )
|| !isTame(unit)
|| isWar(unit) // ignore war dogs etc
|| isHunter(unit) // ignore hunting dogs etc
|| (isContainedInItem(unit) && hasValidMapPos(unit) && isBuiltCageAtPos(unit->pos))
// ignore creatures in built cages to leave zoos alone
// (TODO: allow some kind of slaughter cages which you can place near the butcher)
|| (isContainedInItem(unit) && isInBuiltCage(unit))
|| unit->name.has_name
)
continue;