Пример #1
0
int item_database::scaled_stat( const item_t& item, const dbc_t& dbc, size_t idx, unsigned new_ilevel )
{
  // Safeguard against array overflow, should never happen in any case
  if ( idx >= sizeof_array( item.parsed.data.stat_val ) - 1 )
    return -1;

  if ( item.parsed.data.level == 0 )
    return item.parsed.data.stat_val[ idx ];

  //if ( item.level == ( int ) new_ilevel )
  //  return item.stat_val[ idx ];

  int slot_type = random_suffix_type( &item.parsed.data );
  double item_budget = 0/*, orig_budget = 0*/;

  if ( slot_type != -1 && item.parsed.data.quality > 0 )
  {
    const random_prop_data_t& ilevel_data = dbc.random_property( new_ilevel );
    //const random_prop_data_t& orig_data = dbc.random_property( item.level );

    // Epic/Legendary
    if ( item.parsed.data.quality == 4 || item.parsed.data.quality == 5 )
    {
      item_budget = ilevel_data.p_epic[ slot_type ];
      //orig_budget = orig_data.p_epic[ slot_type ];
    }
    // Rare/Heirloom
    else if ( item.parsed.data.quality == 3 || item.parsed.data.quality == 7 )
    {
      item_budget = ilevel_data.p_rare[ slot_type ];
      //orig_budget = orig_data.p_rare[ slot_type ];
    }
    // Rest
    else
    {
      item_budget = ilevel_data.p_uncommon[ slot_type ];
      //orig_budget = orig_data.p_uncommon[ slot_type ];
    }
  }

  // Precise stat scaling formula for ilevel increase, stats should be
  // spot on.
  if ( item.parsed.data.stat_alloc[ idx ] > 0 /* && orig_budget > 0 */ && item_budget > 0 )
  {
    double v_raw = util::round( item.parsed.data.stat_alloc[ idx ] * item_budget / 10000.0 );
    // Socket penalty is supposedly gone in Warlords of Draenor, but it really does not seem so in the latest alpha.
    // NOTENOTENOTENOTE: Item socket cost penalty multiplier _seems_ to be based on _BASE_ itemlevel, not the upgraded one
    double v_socket_penalty = util::round( item.parsed.data.stat_socket_mul[ idx ] * dbc.item_socket_cost( item.base_item_level() ) );
    return static_cast<int>( v_raw - v_socket_penalty );
  }
  // TODO(?): Should we warn the user that we are using an approximation of
  // the upgraded stats, and that certain stats may be off by one?
  else
    return static_cast<int>( floor( item.parsed.data.stat_val[ idx ] * approx_scale_coefficient( item.parsed.data.level, new_ilevel ) ) );
}
Пример #2
0
static std::pair<std::pair<int, double>, std::pair<int, double> > get_bonus_id_scaling( dbc_t& dbc, const std::vector<const item_bonus_entry_t*>& entries )
{
  for ( size_t i = 0; i < entries.size(); ++i )
  {
    if ( entries[ i ] -> type == ITEM_BONUS_SCALING )
    {
      const scaling_stat_distribution_t* data = dbc.scaling_stat_distribution( entries[ i ] -> value_1 );
      std::pair<const curve_point_t*, const curve_point_t*> curve_data_min = dbc.curve_point( data -> curve_id, data -> min_level );
      std::pair<const curve_point_t*, const curve_point_t*> curve_data_max = dbc.curve_point( data -> curve_id, data -> max_level );

      return std::pair<std::pair<int, double>, std::pair<int, double> >(
          std::pair<int, double>( data -> min_level, curve_data_min.first -> val2 ),
          std::pair<int, double>( data -> max_level, curve_data_max.first -> val2 ) );
    }
  }

  return std::pair<std::pair<int, double>, std::pair<int, double> >( std::pair<int, double>( -1, 0 ), std::pair<int, double>( -1, 0 ) );
}
Пример #3
0
uint32_t item_database::armor_value( const item_data_t* item, const dbc_t& dbc, unsigned item_level )
{
  if ( ! item || item -> quality > 5 )
    return 0;

  unsigned ilevel = item_level ? item_level : item -> level;

  // Shield have separate armor table, bypass normal calculation
  if ( item -> item_class == ITEM_CLASS_ARMOR && item -> item_subclass == ITEM_SUBCLASS_ARMOR_SHIELD )
    return ( uint32_t ) floor( dbc.item_armor_shield( ilevel ).values[ item -> quality ] + 0.5 );

  // Only Cloth, Leather, Mail and Plate armor has innate armor values
  if ( item -> item_subclass == ITEM_SUBCLASS_ARMOR_MISC || item -> item_subclass > ITEM_SUBCLASS_ARMOR_PLATE )
    return 0;

  double m_invtype = 0, m_quality = 0, total_armor = 0;

  switch ( item -> inventory_type )
  {
    case INVTYPE_HEAD:
    case INVTYPE_SHOULDERS:
    case INVTYPE_CHEST:
    case INVTYPE_WAIST:
    case INVTYPE_LEGS:
    case INVTYPE_FEET:
    case INVTYPE_WRISTS:
    case INVTYPE_HANDS:
    case INVTYPE_CLOAK:
    case INVTYPE_ROBE:
    {
      total_armor = dbc.item_armor_total( ilevel ).armor_type[ item -> item_subclass - 1 ];
      m_quality   = dbc.item_armor_quality( ilevel ).values[ item -> quality ];
      unsigned invtype = item -> inventory_type;
      if ( invtype == INVTYPE_ROBE ) invtype = INVTYPE_CHEST;
      m_invtype = dbc.item_armor_inv_type( invtype ).armor_type[ item -> item_subclass - 1 ];
      break;
    }
    default: return 0;
  }

  return ( uint32_t ) floor( total_armor * m_quality * m_invtype + 0.5 );
}
Пример #4
0
bool dbc_override::register_effect( dbc_t& dbc, unsigned effect_id, const std::string& field, double v )
{
  spelleffect_data_t* effect = override_db_.get_mutable_effect( effect_id, dbc.ptr );
  if ( ! effect )
  {
    const spelleffect_data_t* dbc_effect = dbc.effect( effect_id );
    override_db_.clone_spell( dbc_effect -> spell() -> id(), dbc.ptr );
    effect = override_db_.get_mutable_effect( effect_id, dbc.ptr );
  }

  assert( effect );

  effect -> override_field( field, v );

  override_entries_.push_back( dbc_override_entry_t( DBC_OVERRIDE_EFFECT, field, effect_id, v ) );

  return true;
}
Пример #5
0
void rating_t::init( sim_t* sim, dbc_t& dbc, int level, int type )
{
  if ( sim -> debug ) log_t::output( sim, "rating_t::init: level=%d type=%s",
                                     level, util_t::player_type_string( type ) );

  if ( type == ENEMY || type == ENEMY_ADD )
  {
    double max = +1.0E+50;
    spell_haste       = max;
    spell_hit         = max;
    spell_crit        = max;
    attack_haste      = max;
    attack_hit        = max;
    attack_crit       = max;
    ranged_haste      = max;
    ranged_hit        = max;
    ranged_crit       = max;
    expertise         = max;
    dodge             = max;
    parry             = max;
    block             = max;
    mastery           = max;
  }
  else
  {
    spell_haste       = dbc.combat_rating( RATING_SPELL_HASTE,  level );
    spell_hit         = dbc.combat_rating( RATING_SPELL_HIT,    level );
    spell_crit        = dbc.combat_rating( RATING_SPELL_CRIT,   level );
    attack_haste      = dbc.combat_rating( RATING_MELEE_HASTE,  level );
    attack_hit        = dbc.combat_rating( RATING_MELEE_HIT,    level );
    attack_crit       = dbc.combat_rating( RATING_MELEE_CRIT,   level );
    ranged_haste      = dbc.combat_rating( RATING_RANGED_HASTE, level );
    ranged_hit        = dbc.combat_rating( RATING_RANGED_HIT,   level );
    ranged_crit       = dbc.combat_rating( RATING_RANGED_CRIT,  level );
    expertise         = dbc.combat_rating( RATING_EXPERTISE,    level );
    dodge             = dbc.combat_rating( RATING_DODGE,        level );
    parry             = dbc.combat_rating( RATING_PARRY,        level );
    block             = dbc.combat_rating( RATING_BLOCK,        level );
    mastery           = dbc.combat_rating( RATING_MASTERY,      level ) / 100;
  }
}
Пример #6
0
double rating_t::get_attribute_base( sim_t* /* sim */, dbc_t& dbc, int level, player_type class_type, race_type race, base_stat_type stat_type )
{
  double res                       = 0.0;

  switch ( stat_type )
  {
  case BASE_STAT_STRENGTH:           res = dbc.race_base( race ).strength + dbc.attribute_base( class_type, level ).strength; break;
  case BASE_STAT_AGILITY:            res = dbc.race_base( race ).agility + dbc.attribute_base( class_type, level ).agility; break;
  case BASE_STAT_STAMINA:            res = dbc.race_base( race ).stamina + dbc.attribute_base( class_type, level ).stamina; break;
  case BASE_STAT_INTELLECT:          res = dbc.race_base( race ).intellect + dbc.attribute_base( class_type, level ).intellect; break;
  case BASE_STAT_SPIRIT:             res = dbc.race_base( race ).spirit + dbc.attribute_base( class_type, level ).spirit;
                                     if ( race == RACE_HUMAN ) res *= 1.03; break;
  case BASE_STAT_HEALTH:             res = dbc.attribute_base( class_type, level ).base_health; break;
  case BASE_STAT_MANA:               res = dbc.attribute_base( class_type, level ).base_resource; break;
  case BASE_STAT_MELEE_CRIT_PER_AGI: res = dbc.melee_crit_scaling( class_type, level ); break;
  case BASE_STAT_SPELL_CRIT_PER_INT: res = dbc.spell_crit_scaling( class_type, level ); break;
  case BASE_STAT_DODGE_PER_AGI:      res = dbc.dodge_scaling( class_type, level ); break;
  case BASE_STAT_MELEE_CRIT:         res = dbc.melee_crit_base( class_type ); break;
  case BASE_STAT_SPELL_CRIT:         res = dbc.spell_crit_base( class_type ); break;
  case BASE_STAT_MP5:                res = dbc.regen_base( class_type, level ); break;
  case BASE_STAT_SPI_REGEN:          res = dbc.regen_spirit( class_type, level ); break;
  default: break;
  }

  return res;
}
Пример #7
0
std::string dbc::bonus_ids_str( dbc_t& dbc)
{
  std::vector<unsigned> bonus_ids;
  std::stringstream s;

  const item_bonus_entry_t* e = dbc::item_bonus_entries( dbc.ptr );
  while ( e -> id != 0 )
  {
    if ( std::find( bonus_ids.begin(), bonus_ids.end(), e -> bonus_id ) != bonus_ids.end() )
    {
      e++;
      continue;
    }

    // Need at least one "relevant" type for us
    if ( e -> type != ITEM_BONUS_ILEVEL && e -> type != ITEM_BONUS_MOD &&
         e -> type != ITEM_BONUS_SOCKET && e -> type != ITEM_BONUS_SCALING )
    {
      e++;
      continue;
    }

    if ( e -> type == ITEM_BONUS_ILEVEL && e -> value_1 == 0 )
    {
      e++;
      continue;
    }

    bonus_ids.push_back( e -> bonus_id );

    e++;
  }

  std::sort( bonus_ids.begin(), bonus_ids.end() );

  for ( size_t i = 0; i < bonus_ids.size(); ++i )
  {
    std::vector<const item_bonus_entry_t*> entries = dbc.item_bonus( bonus_ids[ i ] );
    std::string desc = get_bonus_id_desc( dbc.ptr, entries );
    std::string suffix = get_bonus_id_suffix( dbc.ptr, entries );
    int ilevel = get_bonus_id_ilevel( entries );
    int sockets = get_bonus_id_sockets( entries );
    std::vector<std::pair<item_mod_type, double> > stats = get_bonus_id_stats( entries );
    std::pair< std::pair<int, double>, std::pair<int, double> > scaling = get_bonus_id_scaling( dbc, entries );

    std::vector<std::string> fields;

    fields.push_back( "bonus_id={ " + util::to_string( bonus_ids[ i ] ) + " }" );
    if ( ! desc.empty() )
    {
      fields.push_back( "desc={ " + desc + " }" );
    }

    if ( ! suffix.empty() )
    {
      fields.push_back( "suffix={ " + suffix + " }" );
    }

    if ( ilevel != 0 )
    {
      fields.push_back( "ilevel_adjust={ " + util::to_string( ilevel ) + " }" );
    }

    if ( sockets > 0 )
    {
      fields.push_back( "socket={ " + util::to_string( sockets ) + " }" );
    }

    if ( stats.size() > 0 )
    {
      std::string stats_str = "stats={ ";
      for ( size_t j = 0; j < stats.size(); ++j )
      {
        stats_str += util::to_string( util::round( stats[ j ].second * 100.0, 0 ) ) + "% ";
        stats_str += util::stat_type_abbrev( util::translate_item_mod( stats[ j ].first ) );
        if ( j < stats.size() - 1 )
        {
          stats_str += ", ";
        }
      }
      fields.push_back( stats_str + " }" );
    }

    if ( scaling.first.first >= 0 )
    {
      std::string str = "ilevel={ ";

      str += util::to_string( scaling.first.second ) + " @plvl " + util::to_string( scaling.first.first );
      str += " - ";
      str += util::to_string( scaling.second.second ) + " @plvl " + util::to_string( scaling.second.first );
      str += " }";
      fields.push_back( str );
    }

    for ( size_t j = 0; j < fields.size(); ++j )
    {
      s << fields[ j ];
      if ( j < fields.size() - 1 )
      {
        s << ", ";
      }
    }

    s << std::endl;
  }

  return s.str();
}
Пример #8
0
uint32_t item_database::weapon_dmg_max( const item_data_t* item, const dbc_t& dbc, unsigned item_level )
{
  return ( uint32_t ) ceil( dbc.weapon_dps( item, item_level ) * item -> delay / 1000.0 *
                            ( 1 + item -> dmg_range / 2 ) + 0.5 );
}
Пример #9
0
uint32_t item_database::weapon_dmg_min( const item_data_t* item, const dbc_t& dbc, unsigned item_level )
{
  return ( uint32_t ) floor( dbc.weapon_dps( item, item_level ) * item -> delay / 1000.0 *
                             ( 1 - item -> dmg_range / 2 ) );
}
Пример #10
0
uint32_t item_database_t::weapon_dmg_max( const item_data_t* item, const dbc_t& dbc )
{
  return ( uint32_t ) floor( dbc.weapon_dps( item -> id ) *
                            dbc.item( item -> id ) -> delay / 1000.0 *
                            ( 1 + dbc.item( item -> id ) -> dmg_range / 2 ) + 0.5 );
}