@ -57,161 +57,161 @@ command_result df_forceequip(color_ostream &out, vector <string> & parameters);
const string forceequip_help =
" ForceEquip moves local items into a unit's inventory. It is typically \n "
" used to equip specific clothing/armor items onto a dwarf, but can also \n "
" be used to put armor onto a war animal or to add unusual items (such \n "
" as crowns) to any unit. \n "
" This plugin can process multiple items in a single call, but will only \n "
" work with a single unit (the first one it finds under the cursor). \n "
" In order to minimize confusion, it is recommended that you use \n "
" forceequip only when you have a unit standing alone atop a pile of \n "
" gear that you would like it to wear. Items which are stored in bins \n "
" or other containers (e.g. chests, armor racks) may also work, but \n "
" piling items on the floor (via a garbage dump activity zone, of the \n "
" DFHack autodump command) is the most reliable way to do it. \n "
" The plugin will ignore any items that are forbidden. Hence, you \n "
" can setup a large pile of surplus gear, walk a unit onto it (or \n "
" pasture an animal on it), unforbid a few items and run forceequip. \n "
" The (forbidden) majority of your gear will remain in-place, ready \n "
" for the next passerby. "
" \n "
" As mentioned above, this plugin can be used to equip items onto \n "
" units (such as animals) which cannot normally equip gear. There's \n "
" an important caveat here - such creatures will automatically drop \n "
" inappropriate gear almost immediately (within 10 game ticks). \n "
" If you want them to retain their equipment, you must forbid it \n "
" AFTER using forceequip to get it into their inventory. \n "
" This technique can also be used to clothe dwarven infants, but \n "
" only if you're able to separate them from their mothers. \n "
" used to equip specific clothing/armor items onto a dwarf, but can also \n "
" be used to put armor onto a war animal or to add unusual items (such \n "
" as crowns) to any unit. \n "
" This plugin can process multiple items in a single call, but will only \n "
" work with a single unit (the first one it finds under the cursor). \n "
" In order to minimize confusion, it is recommended that you use \n "
" forceequip only when you have a unit standing alone atop a pile of \n "
" gear that you would like it to wear. Items which are stored in bins \n "
" or other containers (e.g. chests, armor racks) may also work, but \n "
" piling items on the floor (via a garbage dump activity zone, of the \n "
" DFHack autodump command) is the most reliable way to do it. \n "
" The plugin will ignore any items that are forbidden. Hence, you \n "
" can setup a large pile of surplus gear, walk a unit onto it (or \n "
" pasture an animal on it), unforbid a few items and run forceequip. \n "
" The (forbidden) majority of your gear will remain in-place, ready \n "
" for the next passerby. "
" \n "
" By default, the forceequip plugin will attempt to avoid \n "
" conflicts and outright cheating. For instance, it will skip \n "
" any item which is flagged for use in a job, and will not \n "
" equip more than one piece of clothing/armor onto any given \n "
" body part. These restrictions can be overridden via command \n "
" switches (see examples below) but doing so puts you at greater \n "
" risk of unexpected consequences. For instance, a dwarf who \n "
" is wearing three breastplates will not be able to move very \n "
" quickly. \n "
" \n "
" Items equipped by this plugin DO NOT become owned by the \n "
" recipient. Adult dwarves are free to adjust their own \n "
" wardrobe, and may promptly decide to doff your gear in \n "
" favour of their owned items. Animals, as described above, \n "
" will tend to discard ALL clothing immediately unless it is \n "
" manually forbidden. Armor items seem to be an exception; \n "
" an animal will tend to retain an equipped suit of mail \n "
" even if you neglect to Forbid it. \n "
" \n "
" Please note that armored animals are quite vulnerable to ranged \n "
" attacks. Unlike dwarves, animals cannot block, dodge, or deflect \n "
" arrows, and they are slowed by the weight of their armor. \n "
" \n "
" This plugin currently does not support weapons. \n "
" \n "
" Options: \n "
" here, h - process the unit and item(s) under the cursor. \n "
" - This option is enabled by default since the plugin \n "
" - does not currently support remote equpping. \n "
" As mentioned above, this plugin can be used to equip items onto \n "
" units (such as animals) which cannot normally equip gear. There's \n "
" an important caveat here - such creatures will automatically drop \n "
" inappropriate gear almost immediately (within 10 game ticks). \n "
" If you want them to retain their equipment, you must forbid it \n "
" AFTER using forceequip to get it into their inventory. \n "
" This technique can also be used to clothe dwarven infants, but \n "
" only if you're able to separate them from their mothers. \n "
" \n "
" By default, the forceequip plugin will attempt to avoid \n "
" conflicts and outright cheating. For instance, it will skip \n "
" any item which is flagged for use in a job, and will not \n "
" equip more than one piece of clothing/armor onto any given \n "
" body part. These restrictions can be overridden via command \n "
" switches (see examples below) but doing so puts you at greater \n "
" risk of unexpected consequences. For instance, a dwarf who \n "
" is wearing three breastplates will not be able to move very \n "
" quickly. \n "
" \n "
" Items equipped by this plugin DO NOT become owned by the \n "
" recipient. Adult dwarves are free to adjust their own \n "
" wardrobe, and may promptly decide to doff your gear in \n "
" favour of their owned items. Animals, as described above, \n "
" will tend to discard ALL clothing immediately unless it is \n "
" manually forbidden. Armor items seem to be an exception; \n "
" an animal will tend to retain an equipped suit of mail \n "
" even if you neglect to Forbid it. \n "
" \n "
" Please note that armored animals are quite vulnerable to ranged \n "
" attacks. Unlike dwarves, animals cannot block, dodge, or deflect \n "
" arrows, and they are slowed by the weight of their armor. \n "
" \n "
" This plugin currently does not support weapons. \n "
" \n "
" Options: \n "
" here, h - process the unit and item(s) under the cursor. \n "
" - This option is enabled by default since the plugin \n "
" - does not currently support remote equpping. \n "
" ignore, i - bypasses the usual item eligibility checks (such as \n "
" - \" Never equip gear belonging to another dwarf \" and \n "
" - \" Nobody is allowed to equip a Hive \" .) \n "
" multi, m - bypasses the 1-item-per-bodypart limit, allowing \n "
" - the unit to receive an unlimited amount of gear. \n "
" - Can be used legitimately (e.g. mitten + gauntlet) \n "
" - or for cheating (e.g. twelve breastplates). \n "
" m2, m3, m4 - alters the 1-item-per-bodypart limit, allowing \n "
" - each part to receive 2, 3, or 4 pieces of gear. \n "
" selected, s - rather than processing all items piled at a unit's \n "
" - feet, process only the one item currently selected. \n "
" bodypart, bp - must be followed by a bodypart code (e.g. LH). \n "
" - Instructs the plugin to equip all available items \n "
" - onto this body part only. Typically used in \n "
" - conjunction with the f switch (to over-armor \n "
" - a particular bodypart) or the i switch (to equip \n "
" - an unusual item onto a specific slot). \n "
" - \" Never equip gear belonging to another dwarf \" and \n "
" - \" Nobody is allowed to equip a Hive \" .) \n "
" multi, m - bypasses the 1-item-per-bodypart limit, allowing \n "
" - the unit to receive an unlimited amount of gear. \n "
" - Can be used legitimately (e.g. mitten + gauntlet) \n "
" - or for cheating (e.g. twelve breastplates). \n "
" m2, m3, m4 - alters the 1-item-per-bodypart limit, allowing \n "
" - each part to receive 2, 3, or 4 pieces of gear. \n "
" selected, s - rather than processing all items piled at a unit's \n "
" - feet, process only the one item currently selected. \n "
" bodypart, bp - must be followed by a bodypart code (e.g. LH). \n "
" - Instructs the plugin to equip all available items \n "
" - onto this body part only. Typically used in \n "
" - conjunction with the f switch (to over-armor \n "
" - a particular bodypart) or the i switch (to equip \n "
" - an unusual item onto a specific slot). \n "
" verbose, v - provides detailed narration and error messages. \n "
" - Can be helpful in resolving failures; not needed \n "
" - for casual use. \n "
" \n "
" - Can be helpful in resolving failures; not needed \n "
" - for casual use. \n "
" \n "
" Examples: \n "
" forceequip \n "
" attempts to equip all of the items under the cursor onto the unit \n "
" under the cursor. Uses only clothing/armor items; ignores all \n "
" other types. Equips a maximum of 1 item onto each bodypart, \n "
" and equips only \" appropriate \" items in each slot (e.g. glove \n "
" --> hand). Bypasses any item which might cause a conflict, \n "
" such as a Boot belonging to a different dwarf. \n "
" forceequip bp LH \n "
" attempts to equip all local items onto the left hand of the local \n "
" unit. If the hand is already equipped then nothing will happen, \n "
" and if it is not equipped then only one appropriate item (e.g. \n "
" a single mitten or gauntlet) will be equipped. This command can \n "
" be useful if you don't want to selectively forbid individual items \n "
" and simply want the unit to equip, say, a Helmet while leaving \n "
" the rest of the pile alone. \n "
" forceequip m bp LH \n "
" as above, but will equip ALL appropriate items onto the unit's \n "
" left hand. After running this command, it might end up wearing \n "
" a dozen left-handed mittens. Use with caution, and remember \n "
" that dwarves will tend to drop supernumary items ASAP. \n "
" forceequip m \n "
" as above, but will equip ALL appropriate items onto any \n "
" appropriate bodypart. Tends to put several boots onto the right \n "
" foot while leaving the left foot bare. \n "
" forceequip m2 \n "
" as above, but will equip up to two appropriate items onto each \n "
" bodypart. Helps to balance footwear, but doesn't ensure proper \n "
" placement (e.g. left foot gets two socks, right foot gets two \n "
" shoes). For best results, use \" selected bp LH \" and \n "
" \" selected bp RH \" instead. \n "
" forceequip i \n "
" performs the standard \" equip appropriate items onto appropriate \n "
" bodyparts \" logic, but also includes items that would normally \n "
" be considered ineligible (such as a sock which is owned by \n "
" a different dwarf). \n "
" forceequip bp NECK \n "
" attempts to equip any appropriate gear onto the Neck of the \n "
" local unit. Since the plugin believes that no items are actually \n "
" appropriate for the Neck slot, this command does nothing. \n "
" forceequip i bp NECK \n "
" attempts to equip items from the local pile onto the Neck \n "
" of the local unit. Ignores appropriateness restrictions. \n "
" If there's a millstone or an albatross carcass sitting on \n "
" the same square as the targeted unit, then there's a good \n "
" chance that it will end up around his neck. For precise \n "
" control, remember that you can selectively forbid some of \n "
" the items that are piled on the ground. \n "
" forceequip i m bp NECK \n "
" as above, but equips an unlimited number of items onto the \n "
" targeted bodypart. Effectively, all unforbidden items \n "
" (including helms, millstones, boulders, etc) will be \n "
" moved from the local pile and placed in the dwarf's \n "
" inventory (specifically, on his neck). When used with \n "
" a large pile of goods, this will leave the dwarf heavily \n "
" encumbered and very slow to move. \n "
" forceequip s \n "
" requires that a single item be selected using the k menu. \n "
" This item must occupy the same square as the target unit, \n "
" and must be unforbidden. Attempts to equip this single \n "
" item onto an appropriate slot in the unit's inventory. \n "
" Can serve as a quicker alternative to the selective- \n "
" unforbidding approach described above. \n "
" forceequip s m i bp HD \n "
" equips the selected item onto the unit's head. Ignores \n "
" all possible restrictions and conflicts. If you know \n "
" exactly what you want to equip, and exactly where you \n "
" want it to go, then this is the most straightforward \n "
" and reliable option. \n "
" forceequip v bp QQQ \n "
" guaranteed to fail (and accomplish nothing) because \n "
" there are no bodyparts called QQQ. However, since the \n "
" verbose switch is used, the resulting error messages \n "
" will list every bodypart that the unit DOES possess. \n "
" May be useful if you're unfamiliar with the BP codes \n "
" used by Dwarf Fortress, or if you're experimenting \n "
" with an exotic creature. \n "
" \n "
;
" forceequip \n "
" attempts to equip all of the items under the cursor onto the unit \n "
" under the cursor. Uses only clothing/armor items; ignores all \n "
" other types. Equips a maximum of 1 item onto each bodypart, \n "
" and equips only \" appropriate \" items in each slot (e.g. glove \n "
" --> hand). Bypasses any item which might cause a conflict, \n "
" such as a Boot belonging to a different dwarf. \n "
" forceequip bp LH \n "
" attempts to equip all local items onto the left hand of the local \n "
" unit. If the hand is already equipped then nothing will happen, \n "
" and if it is not equipped then only one appropriate item (e.g. \n "
" a single mitten or gauntlet) will be equipped. This command can \n "
" be useful if you don't want to selectively forbid individual items \n "
" and simply want the unit to equip, say, a Helmet while leaving \n "
" the rest of the pile alone. \n "
" forceequip m bp LH \n "
" as above, but will equip ALL appropriate items onto the unit's \n "
" left hand. After running this command, it might end up wearing \n "
" a dozen left-handed mittens. Use with caution, and remember \n "
" that dwarves will tend to drop supernumary items ASAP. \n "
" forceequip m \n "
" as above, but will equip ALL appropriate items onto any \n "
" appropriate bodypart. Tends to put several boots onto the right \n "
" foot while leaving the left foot bare. \n "
" forceequip m2 \n "
" as above, but will equip up to two appropriate items onto each \n "
" bodypart. Helps to balance footwear, but doesn't ensure proper \n "
" placement (e.g. left foot gets two socks, right foot gets two \n "
" shoes). For best results, use \" selected bp LH \" and \n "
" \" selected bp RH \" instead. \n "
" forceequip i \n "
" performs the standard \" equip appropriate items onto appropriate \n "
" bodyparts \" logic, but also includes items that would normally \n "
" be considered ineligible (such as a sock which is owned by \n "
" a different dwarf). \n "
" forceequip bp NECK \n "
" attempts to equip any appropriate gear onto the Neck of the \n "
" local unit. Since the plugin believes that no items are actually \n "
" appropriate for the Neck slot, this command does nothing. \n "
" forceequip i bp NECK \n "
" attempts to equip items from the local pile onto the Neck \n "
" of the local unit. Ignores appropriateness restrictions. \n "
" If there's a millstone or an albatross carcass sitting on \n "
" the same square as the targeted unit, then there's a good \n "
" chance that it will end up around his neck. For precise \n "
" control, remember that you can selectively forbid some of \n "
" the items that are piled on the ground. \n "
" forceequip i m bp NECK \n "
" as above, but equips an unlimited number of items onto the \n "
" targeted bodypart. Effectively, all unforbidden items \n "
" (including helms, millstones, boulders, etc) will be \n "
" moved from the local pile and placed in the dwarf's \n "
" inventory (specifically, on his neck). When used with \n "
" a large pile of goods, this will leave the dwarf heavily \n "
" encumbered and very slow to move. \n "
" forceequip s \n "
" requires that a single item be selected using the k menu. \n "
" This item must occupy the same square as the target unit, \n "
" and must be unforbidden. Attempts to equip this single \n "
" item onto an appropriate slot in the unit's inventory. \n "
" Can serve as a quicker alternative to the selective- \n "
" unforbidding approach described above. \n "
" forceequip s m i bp HD \n "
" equips the selected item onto the unit's head. Ignores \n "
" all possible restrictions and conflicts. If you know \n "
" exactly what you want to equip, and exactly where you \n "
" want it to go, then this is the most straightforward \n "
" and reliable option. \n "
" forceequip v bp QQQ \n "
" guaranteed to fail (and accomplish nothing) because \n "
" there are no bodyparts called QQQ. However, since the \n "
" verbose switch is used, the resulting error messages \n "
" will list every bodypart that the unit DOES possess. \n "
" May be useful if you're unfamiliar with the BP codes \n "
" used by Dwarf Fortress, or if you're experimenting \n "
" with an exotic creature. \n "
" \n "
;
DFhackCExport command_result plugin_init ( color_ostream & out , vector < PluginCommand > & commands )
{
@ -412,27 +412,27 @@ static bool moveToInventory(MapExtras::MapCache &mc, df::item *item, df::unit *u
command_result df_forceequip ( color_ostream & out , vector < string > & parameters )
{
// The "here" option is hardcoded to true, because the plugin currently doesn't support
// equip-at-a-distance (e.g. grab items within 10 squares of the targeted unit)
// The "here" option is hardcoded to true, because the plugin currently doesn't support
// equip-at-a-distance (e.g. grab items within 10 squares of the targeted unit)
bool here = true ;
// For balance (anti-cheating) reasons, the plugin applies a limit on the number of
// item that can be equipped on any bodypart. This limit defaults to 1 but can be
// overridden with cmdline switches.
// For balance (anti-cheating) reasons, the plugin applies a limit on the number of
// item that can be equipped on any bodypart. This limit defaults to 1 but can be
// overridden with cmdline switches.
int multiEquipLimit = 1 ;
// The plugin applies several pre-checks in order to reduce the risk of conflict
// and unintended side-effects. Most of these checks can be disabled via cmdline
bool ignore = false ;
// By default, the plugin uses all gear piled on the selected square. Optionally,
// it can target only a single item (selected on the k menu) instead
bool selected = false ;
// Most of the plugin's text output is suppressed by default. It can be enabled
// to provide insight into errors, and/or for debugging purposes.
bool verbose = false ;
// By default, the plugin will mate each item to an appropriate bodypart. This
// behaviour can be skipped if the user specifies a particular BP in the cmdline input.
// The plugin applies several pre-checks in order to reduce the risk of conflict
// and unintended side-effects. Most of these checks can be disabled via cmdline
bool ignore = false ;
// By default, the plugin uses all gear piled on the selected square. Optionally,
// it can target only a single item (selected on the k menu) instead
bool selected = false ;
// Most of the plugin's text output is suppressed by default. It can be enabled
// to provide insight into errors, and/or for debugging purposes.
bool verbose = false ;
// By default, the plugin will mate each item to an appropriate bodypart. This
// behaviour can be skipped if the user specifies a particular BP in the cmdline input.
std : : string targetBodyPartCode ;
// Parse the input
// Parse the input
for ( size_t i = 0 ; i < parameters . size ( ) ; i + + )
{
string & p = parameters [ i ] ;
@ -446,34 +446,34 @@ command_result df_forceequip(color_ostream &out, vector <string> & parameters)
{
here = true ;
}
else if ( p = = " ignore " | | p = = " i " )
{
ignore = true ;
}
else if ( p = = " ignore " | | p = = " i " )
{
ignore = true ;
}
else if ( p = = " multi " | | p = = " m " )
{
multiEquipLimit = INT_MAX ;
}
else if ( p = = " m2 " )
{
multiEquipLimit = 2 ;
}
else if ( p = = " m3 " )
{
multiEquipLimit = 3 ;
}
else if ( p = = " m4 " )
{
multiEquipLimit = 4 ;
}
else if ( p = = " selected " | | p = = " s " )
{
selected = true ;
}
else if ( p = = " verbose " | | p = = " v " )
{
verbose = true ;
}
multiEquipLimit = INT_MAX ;
}
else if ( p = = " m2 " )
{
multiEquipLimit = 2 ;
}
else if ( p = = " m3 " )
{
multiEquipLimit = 3 ;
}
else if ( p = = " m4 " )
{
multiEquipLimit = 4 ;
}
else if ( p = = " selected " | | p = = " s " )
{
selected = true ;
}
else if ( p = = " verbose " | | p = = " v " )
{
verbose = true ;
}
else if ( p = = " bodypart " | | p = = " bp " )
{
// must be followed by bodypart code (e.g. NECK)
@ -492,150 +492,150 @@ command_result df_forceequip(color_ostream &out, vector <string> & parameters)
}
}
// Ensure that the map information is available (e.g. a game is actually in-progress)
// Ensure that the map information is available (e.g. a game is actually in-progress)
if ( ! Maps : : IsValid ( ) )
{
out . printerr ( " Map is not available! \n " ) ;
return CR_FAILURE ;
}
// Lookup the cursor position
int cx , cy , cz ;
DFCoord pos_cursor ;
// needs a cursor
if ( ! Gui : : getCursorCoords ( cx , cy , cz ) )
{
out . printerr ( " Cursor position not found. Please enable the cursor. \n " ) ;
return CR_FAILURE ;
}
pos_cursor = DFCoord ( cx , cy , cz ) ;
// Iterate over all units, process the first one whose pos == pos_cursor
df : : unit * targetUnit ;
size_t numUnits = world - > units . all . size ( ) ;
for ( size_t i = 0 ; i < numUnits ; i + + )
{
targetUnit = world - > units . all [ i ] ; // tentatively assume that we have a match; then verify
DFCoord pos_unit ( targetUnit - > pos . x , targetUnit - > pos . y , targetUnit - > pos . z ) ;
if ( pos_unit = = pos_cursor )
break ;
if ( i + 1 = = numUnits )
{
out . printerr ( " No unit found at cursor! \n " ) ;
return CR_FAILURE ;
}
}
// Assert: unit found.
// If a specific bodypart was included in the command arguments, then search for it now
df : : body_part_raw * targetBodyPart = NULL ;
if ( targetBodyPartCode . size ( ) > 0 ) {
for ( int bpIndex = 0 ; bpIndex < targetUnit - > body . body_plan - > body_parts . size ( ) ; bpIndex + + )
{
// Tentatively assume that the part is a match
targetBodyPart = targetUnit - > body . body_plan - > body_parts . at ( bpIndex ) ;
if ( targetBodyPart - > token . compare ( targetBodyPartCode ) = = 0 )
{
// It is indeed a match; exit the loop (while leaving the variable populated)
if ( verbose ) { out . print ( " Matching bodypart (%s) found. \n " , targetBodyPart - > token . c_str ( ) ) ; }
break ;
}
else
{
// Not a match; nullify the variable (it will get re-populated on the next pass through the loop)
if ( verbose ) { out . printerr ( " Bodypart \" %s \" does not match \" %s \" . \n " , targetBodyPart - > token . c_str ( ) , targetBodyPartCode . c_str ( ) ) ; }
targetBodyPart = NULL ;
}
}
if ( ! targetBodyPart )
{
// Loop iteration is complete but no match was found.
out . printerr ( " The unit does not possess a bodypart of type \" %s \" . Please check the spelling or choose a different unit. \n " , targetBodyPartCode . c_str ( ) ) ;
return CR_FAILURE ;
}
}
// Search for item(s)
MapCache mc ;
// iterate over all items, process those where pos == pos_cursor
int itemsEquipped = 0 ;
int itemsFound = 0 ;
int numItems = world - > items . all . size ( ) ; // Normally, we iterate through EVERY ITEM in the world. This is expensive, but currently necessary.
if ( selected ) { numItems = 1 ; } // If the user wants to process only the selected item, then the loop is trivialized (only one pass is needed).
for ( int i = 0 ; i < numItems ; i + + )
{
df : : item * currentItem ;
// Search behaviour depends on whether the operation is driven by cursor location or UI selection
if ( selected )
{
// The "search" is trivial - the selection must always cover either one or zero items
currentItem = Gui : : getSelectedItem ( out ) ;
if ( ! currentItem ) { return CR_FAILURE ; }
}
else
{
// Lookup the current item in the world-space
currentItem = world - > items . all [ i ] ;
// Test the item's position
DFCoord pos_item ( currentItem - > pos . x , currentItem - > pos . y , currentItem - > pos . z ) ;
if ( pos_item ! = pos_cursor )
{
// The item is in the wrong place; skip it
// Note: we do not emit any notification, even with the "verbose" switch, because the search space is enormous and we'd invariably flood the UI with useless text
continue ;
}
// Bypass any forbidden items
else if ( currentItem - > flags . bits . forbid = = 1 )
{
// The item is forbidden; skip it
if ( verbose ) { out . printerr ( " Forbidden item encountered; skipping to next item. \n " ) ; }
}
}
// Test the item; check whether we have any grounds to disqualify/reject it
if ( currentItem - > flags . bits . in_inventory = = 1 )
{
// The item is in a unit's inventory; skip it
if ( verbose ) { out . printerr ( " Inventory item encountered; skipping to next item. \n " ) ; }
}
else
{
itemsFound + + ; // Track the number of items found under the cursor (for feedback purposes)
if ( moveToInventory ( mc , currentItem , targetUnit , targetBodyPart , ignore , multiEquipLimit , verbose ) )
{
// // TODO TEMP EXPERIMENTAL - try to alter the item size in order to conform to its wearer
// currentItem->getRace();
// out.print("Critter size: %d| %d | Armor size: %d", world->raws.creatures.all[targetUnit->race]->caste[targetUnit->caste]->body_size_1, world->raws.creatures.all[targetUnit->race]->caste[targetUnit->caste]->body_size_2, currentItem->getTotalDimension());
itemsEquipped + + ; // Track the number of items successfully processed (for feedback purposes)
}
}
}
if ( itemsFound = = 0 ) {
out . printerr ( " No usable items found at the cursor position. Please choose a different location and try again. \n " ) ;
return CR_OK ;
}
if ( itemsEquipped = = 0 & & ! verbose ) { out . printerr ( " Some items were found but no equipment changes could be made. Use the /verbose switch to display the reasons for failure. \n " ) ; }
if ( itemsEquipped > 0 ) { out . print ( " %d items equipped. \n " , itemsEquipped ) ; }
// At this point, some changes may have been made (such as detaching items from their original position), regardless of whether any equipment changes succeeded.
// Therefore, we must update the map.
mc . WriteAll ( ) ;
// Note: we might expect to recalculate the unit's weight at this point, in order to account for the
// added items. In fact, this recalculation occurs automatically during each dwarf's "turn".
// The slight delay in recalculation is probably not worth worrying about.
// Work complete; report success
return CR_OK ;
// Lookup the cursor position
int cx , cy , cz ;
DFCoord pos_cursor ;
// needs a cursor
if ( ! Gui : : getCursorCoords ( cx , cy , cz ) )
{
out . printerr ( " Cursor position not found. Please enable the cursor. \n " ) ;
return CR_FAILURE ;
}
pos_cursor = DFCoord ( cx , cy , cz ) ;
// Iterate over all units, process the first one whose pos == pos_cursor
df : : unit * targetUnit ;
size_t numUnits = world - > units . all . size ( ) ;
for ( size_t i = 0 ; i < numUnits ; i + + )
{
targetUnit = world - > units . all [ i ] ; // tentatively assume that we have a match; then verify
DFCoord pos_unit ( targetUnit - > pos . x , targetUnit - > pos . y , targetUnit - > pos . z ) ;
if ( pos_unit = = pos_cursor )
break ;
if ( i + 1 = = numUnits )
{
out . printerr ( " No unit found at cursor! \n " ) ;
return CR_FAILURE ;
}
}
// Assert: unit found.
// If a specific bodypart was included in the command arguments, then search for it now
df : : body_part_raw * targetBodyPart = NULL ;
if ( targetBodyPartCode . size ( ) > 0 ) {
for ( int bpIndex = 0 ; bpIndex < targetUnit - > body . body_plan - > body_parts . size ( ) ; bpIndex + + )
{
// Tentatively assume that the part is a match
targetBodyPart = targetUnit - > body . body_plan - > body_parts . at ( bpIndex ) ;
if ( targetBodyPart - > token . compare ( targetBodyPartCode ) = = 0 )
{
// It is indeed a match; exit the loop (while leaving the variable populated)
if ( verbose ) { out . print ( " Matching bodypart (%s) found. \n " , targetBodyPart - > token . c_str ( ) ) ; }
break ;
}
else
{
// Not a match; nullify the variable (it will get re-populated on the next pass through the loop)
if ( verbose ) { out . printerr ( " Bodypart \" %s \" does not match \" %s \" . \n " , targetBodyPart - > token . c_str ( ) , targetBodyPartCode . c_str ( ) ) ; }
targetBodyPart = NULL ;
}
}
if ( ! targetBodyPart )
{
// Loop iteration is complete but no match was found.
out . printerr ( " The unit does not possess a bodypart of type \" %s \" . Please check the spelling or choose a different unit. \n " , targetBodyPartCode . c_str ( ) ) ;
return CR_FAILURE ;
}
}
// Search for item(s)
MapCache mc ;
// iterate over all items, process those where pos == pos_cursor
int itemsEquipped = 0 ;
int itemsFound = 0 ;
int numItems = world - > items . all . size ( ) ; // Normally, we iterate through EVERY ITEM in the world. This is expensive, but currently necessary.
if ( selected ) { numItems = 1 ; } // If the user wants to process only the selected item, then the loop is trivialized (only one pass is needed).
for ( int i = 0 ; i < numItems ; i + + )
{
df : : item * currentItem ;
// Search behaviour depends on whether the operation is driven by cursor location or UI selection
if ( selected )
{
// The "search" is trivial - the selection must always cover either one or zero items
currentItem = Gui : : getSelectedItem ( out ) ;
if ( ! currentItem ) { return CR_FAILURE ; }
}
else
{
// Lookup the current item in the world-space
currentItem = world - > items . all [ i ] ;
// Test the item's position
DFCoord pos_item ( currentItem - > pos . x , currentItem - > pos . y , currentItem - > pos . z ) ;
if ( pos_item ! = pos_cursor )
{
// The item is in the wrong place; skip it
// Note: we do not emit any notification, even with the "verbose" switch, because the search space is enormous and we'd invariably flood the UI with useless text
continue ;
}
// Bypass any forbidden items
else if ( currentItem - > flags . bits . forbid = = 1 )
{
// The item is forbidden; skip it
if ( verbose ) { out . printerr ( " Forbidden item encountered; skipping to next item. \n " ) ; }
}
}
// Test the item; check whether we have any grounds to disqualify/reject it
if ( currentItem - > flags . bits . in_inventory = = 1 )
{
// The item is in a unit's inventory; skip it
if ( verbose ) { out . printerr ( " Inventory item encountered; skipping to next item. \n " ) ; }
}
else
{
itemsFound + + ; // Track the number of items found under the cursor (for feedback purposes)
if ( moveToInventory ( mc , currentItem , targetUnit , targetBodyPart , ignore , multiEquipLimit , verbose ) )
{
// // TODO TEMP EXPERIMENTAL - try to alter the item size in order to conform to its wearer
// currentItem->getRace();
// out.print("Critter size: %d| %d | Armor size: %d", world->raws.creatures.all[targetUnit->race]->caste[targetUnit->caste]->body_size_1, world->raws.creatures.all[targetUnit->race]->caste[targetUnit->caste]->body_size_2, currentItem->getTotalDimension());
itemsEquipped + + ; // Track the number of items successfully processed (for feedback purposes)
}
}
}
if ( itemsFound = = 0 ) {
out . printerr ( " No usable items found at the cursor position. Please choose a different location and try again. \n " ) ;
return CR_OK ;
}
if ( itemsEquipped = = 0 & & ! verbose ) { out . printerr ( " Some items were found but no equipment changes could be made. Use the /verbose switch to display the reasons for failure. \n " ) ; }
if ( itemsEquipped > 0 ) { out . print ( " %d items equipped. \n " , itemsEquipped ) ; }
// At this point, some changes may have been made (such as detaching items from their original position), regardless of whether any equipment changes succeeded.
// Therefore, we must update the map.
mc . WriteAll ( ) ;
// Note: we might expect to recalculate the unit's weight at this point, in order to account for the
// added items. In fact, this recalculation occurs automatically during each dwarf's "turn".
// The slight delay in recalculation is probably not worth worrying about.
// Work complete; report success
return CR_OK ;
}