|
|
|
@ -1022,3 +1022,300 @@ df::proj_itemst *Items::makeProjectile(MapExtras::MapCache &mc, df::item *item)
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|