Add Items::getItemBaseValue and Items::getValue, available from Lua

develop
Quietust 2014-04-25 11:04:21 -05:00
parent 57fbb1004b
commit 0f4684f29d
5 changed files with 326 additions and 0 deletions

@ -1252,6 +1252,9 @@ the flags in the job item.</p>
<li><p class="first"><tt class="docutils literal">dfhack.job.isSuitableMaterial(job_item, mat_type, mat_index)</tt></p> <li><p class="first"><tt class="docutils literal">dfhack.job.isSuitableMaterial(job_item, mat_type, mat_index)</tt></p>
<p>Likewise, if replacing material.</p> <p>Likewise, if replacing material.</p>
</li> </li>
<li><p class="first"><tt class="docutils literal">dfhack.job.getName(job)</tt></p>
<p>Returns the job's description, as seen in the Units and Jobs screens.</p>
</li>
</ul> </ul>
</div> </div>
<div class="section" id="units-module"> <div class="section" id="units-module">
@ -1420,6 +1423,12 @@ Returns <em>false</em> in case of error.</p>
<li><p class="first"><tt class="docutils literal">dfhack.items.getSubtypeDef(item_type, subtype)</tt></p> <li><p class="first"><tt class="docutils literal">dfhack.items.getSubtypeDef(item_type, subtype)</tt></p>
<p>Returns the raw definition for the given item type and subtype, or <em>nil</em> if invalid.</p> <p>Returns the raw definition for the given item type and subtype, or <em>nil</em> if invalid.</p>
</li> </li>
<li><p class="first"><tt class="docutils literal">dfhack.items.getItemBaseValue(item_type, subtype, material, mat_index)</tt></p>
<p>Calculates the base value for an item of the specified type and material.</p>
</li>
<li><p class="first"><tt class="docutils literal">dfhack.items.getValue(item)</tt></p>
<p>Calculates the Basic Value of an item, as seen in the View Item screen.</p>
</li>
</ul> </ul>
</div> </div>
<div class="section" id="maps-module"> <div class="section" id="maps-module">

@ -979,6 +979,10 @@ Job module
Likewise, if replacing material. Likewise, if replacing material.
* ``dfhack.job.getName(job)``
Returns the job's description, as seen in the Units and Jobs screens.
Units module Units module
------------ ------------
@ -1187,6 +1191,14 @@ Items module
Returns the raw definition for the given item type and subtype, or *nil* if invalid. Returns the raw definition for the given item type and subtype, or *nil* if invalid.
* ``dfhack.items.getItemBaseValue(item_type, subtype, material, mat_index)``
Calculates the base value for an item of the specified type and material.
* ``dfhack.items.getValue(item)``
Calculates the Basic Value of an item, as seen in the View Item screen.
Maps module Maps module
----------- -----------

@ -1476,6 +1476,8 @@ static const LuaWrapper::FunctionReg dfhack_items_module[] = {
WRAPM(Items, isCasteMaterial), WRAPM(Items, isCasteMaterial),
WRAPM(Items, getSubtypeCount), WRAPM(Items, getSubtypeCount),
WRAPM(Items, getSubtypeDef), WRAPM(Items, getSubtypeDef),
WRAPM(Items, getItemBaseValue),
WRAPM(Items, getValue),
WRAPN(moveToGround, items_moveToGround), WRAPN(moveToGround, items_moveToGround),
WRAPN(moveToContainer, items_moveToContainer), WRAPN(moveToContainer, items_moveToContainer),
WRAPN(moveToBuilding, items_moveToBuilding), WRAPN(moveToBuilding, items_moveToBuilding),

@ -173,5 +173,11 @@ DFHACK_EXPORT bool remove(MapExtras::MapCache &mc, df::item *item, bool no_uncat
/// Detaches the items from its current location and turns it into a projectile /// Detaches the items from its current location and turns it into a projectile
DFHACK_EXPORT df::proj_itemst *makeProjectile(MapExtras::MapCache &mc, df::item *item); DFHACK_EXPORT df::proj_itemst *makeProjectile(MapExtras::MapCache &mc, df::item *item);
/// Gets value of base-quality item with specified type and material
DFHACK_EXPORT int getItemBaseValue(int16_t item_type, int16_t item_subtype, int16_t mat_type, int32_t mat_subtype);
/// Gets the value of a specific item, ignoring civ values and trade agreements
DFHACK_EXPORT int getValue(df::item *item);
} }
} }

@ -1022,3 +1022,300 @@ df::proj_itemst *Items::makeProjectile(MapExtras::MapCache &mc, df::item *item)
return proj; return proj;
} }
int Items::getItemBaseValue(int16_t item_type, int16_t item_subtype, int16_t mat_type, int32_t mat_subtype)
{
int value = 0;
switch (item_type)
{
case item_type::BAR:
case item_type::SMALLGEM:
case item_type::BLOCKS:
case item_type::SKIN_TANNED:
value = 5;
break;
case item_type::ROUGH:
case item_type::BOULDER:
case item_type::WOOD:
value = 3;
break;
case item_type::DOOR:
case item_type::FLOODGATE:
case item_type::BED:
case item_type::CHAIR:
case item_type::CHAIN:
case item_type::FLASK:
case item_type::GOBLET:
case item_type::INSTRUMENT:
case item_type::TOY:
case item_type::CAGE:
case item_type::BARREL:
case item_type::BUCKET:
case item_type::ANIMALTRAP:
case item_type::TABLE:
case item_type::COFFIN:
case item_type::BOX:
case item_type::BIN:
case item_type::ARMORSTAND:
case item_type::WEAPONRACK:
case item_type::CABINET:
case item_type::FIGURINE:
case item_type::AMULET:
case item_type::SCEPTER:
case item_type::CROWN:
case item_type::RING:
case item_type::EARRING:
case item_type::BRACELET:
case item_type::GEM:
case item_type::ANVIL:
case item_type::TOTEM:
case item_type::BACKPACK:
case item_type::QUIVER:
case item_type::BALLISTAARROWHEAD:
case item_type::PIPE_SECTION:
case item_type::HATCH_COVER:
case item_type::GRATE:
case item_type::QUERN:
case item_type::MILLSTONE:
case item_type::SPLINT:
case item_type::CRUTCH:
case item_type::SLAB:
case item_type::BOOK:
value = 10;
break;
case item_type::WINDOW:
case item_type::STATUE:
value = 25;
break;
case item_type::CORPSE:
case item_type::CORPSEPIECE:
case item_type::REMAINS:
return 0;
case item_type::WEAPON:
if (item_subtype >= 0 && item_subtype < world->raws.itemdefs.weapons.size())
value = world->raws.itemdefs.weapons[item_subtype]->value;
else
value = 10;
break;
case item_type::ARMOR:
if (item_subtype >= 0 && item_subtype < world->raws.itemdefs.armor.size())
value = world->raws.itemdefs.armor[item_subtype]->value;
else
value = 10;
break;
case item_type::SHOES:
if (item_subtype >= 0 && item_subtype < world->raws.itemdefs.shoes.size())
value = world->raws.itemdefs.shoes[item_subtype]->value;
else
value = 5;
break;
case item_type::SHIELD:
if (item_subtype >= 0 && item_subtype < world->raws.itemdefs.shields.size())
value = world->raws.itemdefs.shields[item_subtype]->value;
else
value = 10;
break;
case item_type::HELM:
if (item_subtype >= 0 && item_subtype < world->raws.itemdefs.helms.size())
value = world->raws.itemdefs.helms[item_subtype]->value;
else
value = 10;
break;
case item_type::GLOVES:
if (item_subtype >= 0 && item_subtype < world->raws.itemdefs.gloves.size())
value = world->raws.itemdefs.gloves[item_subtype]->value;
else
value = 5;
break;
case item_type::AMMO:
if (item_subtype >= 0 && item_subtype < world->raws.itemdefs.ammo.size())
value = world->raws.itemdefs.ammo[item_subtype]->value;
else
value = 1;
break;
case item_type::MEAT:
case item_type::PLANT:
case item_type::LEAVES:
case item_type::CHEESE:
value = 2;
break;
case item_type::FISH:
case item_type::FISH_RAW:
case item_type::EGG:
value = 2;
if (mat_type >= 0 && mat_type < world->raws.creatures.all.size())
{
auto creature = world->raws.creatures.all[mat_type];
if (mat_subtype >= 0 && mat_type < creature->caste.size())
{
auto caste = creature->caste[mat_subtype];
mat_type = caste->misc.bone_mat;
mat_subtype = caste->misc.bone_matidx;
}
}
break;
case item_type::VERMIN:
value = 0;
if (mat_type >= 0 && mat_type < world->raws.creatures.all.size())
{
auto creature = world->raws.creatures.all[mat_type];
if (mat_subtype >= 0 && mat_type < creature->caste.size())
value = creature->caste[mat_subtype]->misc.petvalue;
}
value /= 2;
if (!value)
return 1;
return value;
case item_type::PET:
if (mat_type >= 0 && mat_type < world->raws.creatures.all.size())
{
auto creature = world->raws.creatures.all[mat_type];
if (mat_subtype >= 0 && mat_type < creature->caste.size())
return creature->caste[mat_subtype]->misc.petvalue;
}
return 0;
case item_type::SEEDS:
case item_type::DRINK:
case item_type::POWDER_MISC:
case item_type::LIQUID_MISC:
case item_type::COIN:
case item_type::GLOB:
case item_type::ORTHOPEDIC_CAST:
value = 1;
break;
case item_type::THREAD:
value = 6;
break;
case item_type::CLOTH:
value = 7;
break;
case item_type::PANTS:
if (item_subtype >= 0 && item_subtype < world->raws.itemdefs.pants.size())
value = world->raws.itemdefs.pants[item_subtype]->value;
else
value = 10;
break;
case item_type::CATAPULTPARTS:
case item_type::BALLISTAPARTS:
case item_type::TRAPPARTS:
value = 30;
break;
case item_type::SIEGEAMMO:
case item_type::TRACTION_BENCH:
value = 20;
break;
case item_type::TRAPCOMP:
if (item_subtype >= 0 && item_subtype < world->raws.itemdefs.trapcomps.size())
value = world->raws.itemdefs.trapcomps[item_subtype]->value;
else
value = 10;
break;
case item_type::FOOD:
return 10;
// case item_type::ROCK:
default:
return 0;
case item_type::TOOL:
if (item_subtype >= 0 && item_subtype < world->raws.itemdefs.tools.size())
value = world->raws.itemdefs.tools[item_subtype]->value;
else
value = 10;
break;
}
MaterialInfo mat;
if (mat.decode(mat_type, mat_subtype))
value *= mat.material->material_value;
return value;
}
int Items::getValue(df::item *item)
{
CHECK_NULL_POINTER(item);
int16_t item_type = item->getType();
int16_t item_subtype = item->getSubtype();
int16_t mat_type = item->getMaterial();
int32_t mat_subtype = item->getMaterialIndex();
// Get base value for item type, subtype, and material
int value = getItemBaseValue(item_type, item_subtype, mat_type, mat_subtype);
// Ignore entity value modifications
// Improve value based on quality
int quality = item->getQuality();
value *= (quality + 1);
if (quality == 5)
value *= 2;
// Add improvement values
int impValue = item->getThreadDyeValue(NULL) + item->getImprovementsValue(NULL);
if (item_type == item_type::AMMO) // Ammo improvements are worth less
impValue /= 30;
value += impValue;
// Degrade value due to wear
switch (item->getWear())
{
case 1:
value = value * 3 / 4;
break;
case 2:
value = value / 2;
break;
case 3:
value = value / 4;
break;
}
// Ignore value bonuses from magic, since that never actually happens
// Artifacts have 10x value
if (item->flags.bits.artifact_mood)
value *= 10;
// Boost value from stack size
value *= item->getStackSize();
// ...but not for coins
if (item_type == item_type::COIN)
{
value /= 500;
if (!value)
value = 1;
}
// Handle vermin swarms
if (item_type == item_type::VERMIN || item_type == item_type::PET)
{
int divisor = world->raws.creatures.all[mat_type]->caste[mat_subtype]->misc.petvalue_divisor;
if (divisor > 1)
value /= divisor;
}
return value;
}