Example #1
0
int wowhead_t::parse_gem( item_t&            item,
                          const std::string& gem_id,
                          bool               ptr,
                          cache::behavior_t  caching )
{
  if ( gem_id.empty() || gem_id == "0" )
    return GEM_NONE;

  xml_node_t* node = download_id( item.sim, gem_id, caching, ptr );
  if ( ! node )
  {
    if ( caching != cache::ONLY )
      item.sim -> errorf( "Player %s unable to download gem id %s from wowhead\n", item.player -> name(), gem_id.c_str() );
    return GEM_NONE;
  }

  int gem_type = GEM_NONE;

  std::string color_str;
  if ( xml_t::get_value( color_str, node, "subclass/cdata" ) )
  {
    std::string::size_type pos = color_str.find( ' ' );
    if ( pos != std::string::npos ) color_str.erase( pos );
    armory_t::format( color_str );
    gem_type = util_t::parse_gem_type( color_str );

    if ( gem_type == GEM_META )
    {
      std::string name_str;
      if ( xml_t::get_value( name_str, node, "name/cdata" ) )
      {
        std::string::size_type pos = name_str.find( " Diamond" );
        if ( pos != std::string::npos ) name_str.erase( pos );
        armory_t::format( name_str );
        item.armory_gems_str += "_";
        item.armory_gems_str += name_str;
      }
    }
    else
    {
      std::string stats_str;
      if ( xml_t::get_value( stats_str, node, "jsonEquip/cdata" ) )
      {
        parse_stats( item.armory_gems_str, stats_str );
      }
    }
  }

  return gem_type;
}
Example #2
0
bool wowhead::download_glyph( player_t*          player,
                              std::string&       glyph_name,
                              const std::string& glyph_id,
                              wowhead_e          source,
                              cache::behavior_e  caching )
{
    unsigned glyphid = strtoul( glyph_id.c_str(), nullptr, 10 );
    std::shared_ptr<xml_node_t> node = download_id( player -> sim, glyphid, caching, source );
    if ( ! node || ! node -> get_value( glyph_name, "name/cdata" ) )
    {
        if ( caching != cache::ONLY )
            player -> sim -> errorf( "Unable to download glyph id %s from wowhead\n", glyph_id.c_str() );
        return false;
    }
    return true;
}
Example #3
0
bool wowhead_t::download_glyph( player_t*          player,
                                std::string&       glyph_name,
                                const std::string& glyph_id,
                                bool               ptr,
                                cache::behavior_t  caching )
{
  xml_node_t* node = download_id( player -> sim, glyph_id, caching, ptr );
  if ( ! node || ! xml_t::get_value( glyph_name, node, "name/cdata" ) )
  {
    if ( caching != cache::ONLY )
      player -> sim -> errorf( "Unable to download glyph id %s from wowhead\n", glyph_id.c_str() );
    return false;
  }

  if (      glyph_name.substr( 0, 9 ) == "Glyph of " ) glyph_name.erase( 0, 9 );
  else if ( glyph_name.substr( 0, 8 ) == "Glyph - "  ) glyph_name.erase( 0, 8 );
  armory_t::format( glyph_name );
  return true;
}
Example #4
0
bool wowhead::download_item_data( item_t&            item,
                                  cache::behavior_e  caching,
                                  wowhead_e          source )
{
    std::shared_ptr<xml_node_t> xml = item.xml = download_id( item.sim, item.parsed.data.id, caching, source );

    if ( ! xml )
    {
        if ( caching != cache::ONLY )
            item.sim -> errorf( "Player %s unable to download item id '%u' from wowhead at slot %s.\n", item.player -> name(), item.parsed.data.id, item.slot_name() );
        return false;
    }

    try
    {
        int id;
        if ( ! xml -> get_value( id, "item/id" ) ) throw( "id" );
        item.parsed.data.id = id;

        if ( ! xml -> get_value( item.name_str, "name/cdata" ) ) throw( "name" );
        util::tokenize( item.name_str );

        xml -> get_value( item.icon_str, "icon/cdata" );

        if ( ! xml -> get_value( item.parsed.data.level, "level/." ) ) throw( "level" );

        if ( ! xml -> get_value( item.parsed.data.quality, "quality/id" ) ) throw( "quality" );

        std::string jsonequipdata, jsondata;
        xml -> get_value( jsonequipdata, "jsonEquip/cdata" );
        jsonequipdata = "{" + jsonequipdata + "}";
        xml -> get_value( jsondata, "json/cdata" );
        jsondata = "{" + jsondata + "}";

        rapidjson::Document json, jsonequip;
        json.Parse< 0 >( jsondata.c_str() );
        jsonequip.Parse< 0 >( jsonequipdata.c_str() );

        if ( json.HasParseError() )
        {
            item.sim -> errorf( "Unable to parse JSON data for item id '%u': %s",
                                id, json.GetParseError() );
            return false;
        }

        if ( jsonequip.HasParseError() )
        {
            item.sim -> errorf( "Unable to parse JSON data for item id '%u': %s",
                                id, jsonequip.GetParseError() );
            return false;
        }

        if ( item.sim -> debug )
        {
            rapidjson::StringBuffer b;
            rapidjson::PrettyWriter< rapidjson::StringBuffer > writer( b );

            json.Accept( writer );
            item.sim -> out_debug.raw() << b.GetString();

            jsonequip.Accept( writer );
            item.sim -> out_debug.raw() << b.GetString();
        }

        if ( ! json.HasMember( "slot" ) )
            throw( "inventory type" );

        if ( ! json.HasMember( "classs" ) )
            throw( "item class" );

        if ( ! json.HasMember( "subclass" ) )
            throw( "item subclass" );

        item.parsed.data.inventory_type = json[ "slot" ].GetInt();
        item.parsed.data.item_class = json[ "classs" ].GetInt();
        item.parsed.data.item_subclass = json[ "subclass" ].GetInt();
        if ( item.parsed.data.item_subclass < 0 )
            item.parsed.data.item_subclass = 0;

        if ( json.HasMember( "reqlevel" ) )
            item.parsed.data.req_level = json[ "reqlevel" ].GetInt();

        if ( json.HasMember( "raidfinder" ) )
            item.parsed.data.type_flags |= RAID_TYPE_LFR;

        if ( json.HasMember( "heroic" ) )
            item.parsed.data.type_flags |= RAID_TYPE_HEROIC;

        if ( json.HasMember( "mythic" ) )
            item.parsed.data.type_flags |= RAID_TYPE_MYTHIC;

        if ( json.HasMember( "warforged" ) )
            item.parsed.data.type_flags |= RAID_TYPE_WARFORGED;

        if ( item.parsed.data.item_class == ITEM_CLASS_WEAPON )
        {
            if ( ! jsonequip.HasMember( "dmgrange" ) )
                throw( "weapon damage range" );

            if ( ! jsonequip.HasMember( "speed" ) )
                throw( "weapon speed" );
        }

        if ( jsonequip.HasMember( "reqskill" ) )
            item.parsed.data.req_skill = jsonequip[ "reqskill" ].GetInt();

        if ( jsonequip.HasMember( "reqskillrank" ) )
            item.parsed.data.req_skill_level = jsonequip[ "reqskillrank" ].GetInt();

        // Todo binding type, needs htmlTooltip parsing
        if ( item.parsed.data.item_class == ITEM_CLASS_WEAPON )
        {
            item.parsed.data.delay = jsonequip[ "speed" ].GetDouble() * 1000.0;
            item.parsed.data.dmg_range = jsonequip[ "dmgrange" ].GetDouble();
        }

        int races = -1;
        if ( jsonequip.HasMember( "races" ) )
            races = jsonequip[ "races" ].GetInt();
        item.parsed.data.race_mask = races;

        int classes = -1;
        if ( jsonequip.HasMember( "classes" ) )
            classes = jsonequip[ "classes" ].GetInt();
        item.parsed.data.class_mask = classes;

        size_t n = 0;
        stat_e hybrid_stat = STAT_NONE;
        for ( rapidjson::Value::ConstMemberIterator i = jsonequip.MemberBegin();
                i != jsonequip.MemberEnd() && n < sizeof_array( item.parsed.data.stat_type_e ); i++ )
        {
            stat_e type = util::parse_stat_type( i -> name.GetString() );
            // wowhead josnEquip contains redundant entries for queries, take note so we can purge
            if ( type == STAT_STR_AGI || type == STAT_STR_INT || type == STAT_AGI_INT )
                hybrid_stat = type;
        }

        for ( rapidjson::Value::ConstMemberIterator i = jsonequip.MemberBegin();
                i != jsonequip.MemberEnd() && n < sizeof_array( item.parsed.data.stat_type_e ); i++ )
        {
            stat_e type = util::parse_stat_type( i -> name.GetString() );
            if ( type == STAT_NONE || type == STAT_ARMOR || util::translate_stat( type ) == ITEM_MOD_NONE )
                continue;

            // If we have a hybrid stat, don't record the excess STR/INT/AGI entries
            if ( hybrid_stat != STAT_NONE && ( type == STAT_STRENGTH || type == STAT_INTELLECT || type == STAT_AGILITY ) )
                continue;

            item.parsed.data.stat_type_e[ n ] = util::translate_stat( type );
            item.parsed.data.stat_val[ n ] = i -> value.GetInt();
            n++;

            // Soo, weapons need a flag to indicate caster weapon for correct DPS calculation.
            if ( item.parsed.data.delay > 0 && (
                        item.parsed.data.stat_type_e[ n - 1 ] == ITEM_MOD_INTELLECT ||
                        item.parsed.data.stat_type_e[ n - 1 ] == ITEM_MOD_SPIRIT ||
                        item.parsed.data.stat_type_e[ n - 1 ] == ITEM_MOD_SPELL_POWER ) )
                item.parsed.data.flags_2 |= ITEM_FLAG2_CASTER_WEAPON;
        }

        int n_sockets = 0;
        if ( jsonequip.HasMember( "nsockets" ) )
            n_sockets = jsonequip[ "nsockets" ].GetUint();

        assert( n_sockets <= static_cast< int >( sizeof_array( item.parsed.data.socket_color ) ) );
        for ( int i = 0; i < n_sockets; i++ )
        {
            std::string socket_str = str::format( "socket%d", i + 1 );
            if ( jsonequip.HasMember( socket_str.c_str() ) )
                item.parsed.data.socket_color[ i ] = jsonequip[ socket_str.c_str() ].GetUint();
        }

        if ( jsonequip.HasMember( "socketbonus" ) )
            item.parsed.data.id_socket_bonus = jsonequip[ "socketbonus" ].GetUint();

        if ( jsonequip.HasMember( "itemset" ) )
            item.parsed.data.id_set =  std::abs( jsonequip[ "itemset" ].GetInt() );

        // Sad to the face
        std::string htmltooltip;
        xml -> get_value( htmltooltip, "htmlTooltip/cdata" );

        // Parse out Equip: and On use: strings
        int spell_idx = 0;

        std::shared_ptr<xml_node_t> htmltooltip_xml = xml_node_t::create( item.sim, htmltooltip );
        //htmltooltip_xml -> print( item.sim -> output_file, 2 );
        std::vector<xml_node_t*> spell_links = htmltooltip_xml -> get_nodes( "span" );
        for ( size_t i = 0; i < spell_links.size(); i++ )
        {
            int trigger_type = -1;
            unsigned spell_id = 0;

            std::string v;
            if ( spell_links[ i ] -> get_value( v, "." ) && v != "Equip: " && v != "Use: " )
                continue;

            if ( v == "Use: " )
                trigger_type = ITEM_SPELLTRIGGER_ON_USE;
            else if ( v == "Equip: " )
                trigger_type = ITEM_SPELLTRIGGER_ON_EQUIP;

            std::string url;
            if ( ! spell_links[ i ] -> get_value( url, "a/href" ) )
                continue;

            size_t begin = url.rfind( "=" );
            if ( begin == std::string::npos )
                continue;
            else
                begin++;

            spell_id = util::to_unsigned( url.substr( begin ) );
            if ( spell_id > 0 && trigger_type != -1 )
            {
                item.parsed.data.id_spell[ spell_idx ] = spell_id;
                item.parsed.data.trigger_spell[ spell_idx ] = trigger_type;
                spell_idx++;
            }
        }
    }
    catch ( const char* fieldname )
    {
        std::string error_str;

        xml -> get_value( error_str, "error/." );

        if ( caching != cache::ONLY )
            item.sim -> errorf( "Wowhead (%s): Player %s unable to parse item '%u' %s in slot '%s': %s\n",
                                source_desc_str( source ).c_str(), item.player -> name(), item.parsed.data.id,
                                fieldname, item.slot_name(), error_str.c_str() );
        return false;
    }

    return true;
}
Example #5
0
bool wowhead_t::download_slot( item_t&            item,
                               const std::string& item_id,
                               const std::string& enchant_id,
                               const std::string& addon_id,
                               const std::string& reforge_id,
                               const std::string& rsuffix_id,
                               const std::string  gem_ids[ 3 ],
                               bool               ptr,
                               cache::behavior_t  caching )
{
  player_t* p = item.player;

  xml_node_t* node = download_id( item.sim, item_id, caching, ptr );
  if ( ! node )
  {
    if ( caching != cache::ONLY )
      item.sim -> errorf( "Player %s unable to download item id '%s' from wowhead at slot %s.\n", p -> name(), item_id.c_str(), item.slot_name() );
    return false;
  }

  if ( ! parse_item_name( item, node ) )
  {
    item.sim -> errorf( "Player %s unable to determine item name for id '%s' at slot %s.\n", p -> name(), item_id.c_str(), item.slot_name() );
    return false;
  }

  if ( ! parse_item_quality( item, node ) )
  {
    item.sim -> errorf( "Player %s unable to determine item quality for id '%s' at slot %s.\n", p -> name(), item_id.c_str(), item.slot_name() );
    return false;
  }

  if ( ! parse_item_level( item, node ) )
  {
    item.sim -> errorf( "Player %s unable to determine item level for id '%s' at slot %s.\n", p -> name(), item_id.c_str(), item.slot_name() );
    return false;
  }

  if ( ! parse_item_heroic( item, node ) )
  {
    item.sim -> errorf( "Player %s unable to determine heroic flag for id '%s' at slot %s.\n", p -> name(), item_id.c_str(), item.slot_name() );
    return false;
  }

  if ( ! parse_item_lfr( item, node ) )
  {
    item.sim -> errorf( "Player %s unable to determine LFR flag for id '%s' at slot %s.\n", p -> name(), item_id.c_str(), item.slot_name() );
    return false;
  }

  if ( ! parse_item_armor_type( item, node ) )
  {
    item.sim -> errorf( "Player %s unable to determine armor type for id %s at slot %s.\n", p -> name(), item_id.c_str(), item.slot_name() );
    return false;
  }

  if ( ! parse_item_stats( item, node ) )
  {
    item.sim -> errorf( "Player %s unable to determine stats for item '%s' at slot %s.\n", p -> name(), item.name(), item.slot_name() );
    return false;
  }

  if ( ! parse_weapon( item, node ) )
  {
    item.sim -> errorf( "Player %s unable to determine weapon info for item '%s' at slot %s.\n", p -> name(), item.name(), item.slot_name() );
    return false;
  }

  if ( ! parse_item_reforge( item, node ) )
  {
    item.sim -> errorf( "Player %s unable to determine reforge for item '%s' at slot %s.\n", p -> name(), item.name(), item.slot_name() );
    return false;
  }

  if ( ! parse_gems( item, node, gem_ids ) )
  {
    item.sim -> errorf( "Player %s unable to determine gems for item '%s' at slot %s.\n", p -> name(), item.name(), item.slot_name() );
    return false;
  }

  if ( ! enchant_t::download( item, enchant_id ) )
  {
    item.sim -> errorf( "Player %s unable to parse enchant id %s for item \"%s\" at slot %s.\n", p -> name(), enchant_id.c_str(), item.name(), item.slot_name() );
    //return false;
  }

  if ( ! enchant_t::download_addon( item, addon_id ) )
  {
    item.sim -> errorf( "Player %s unable to parse addon id %s for item \"%s\" at slot %s.\n", p -> name(), addon_id.c_str(), item.name(), item.slot_name() );
    //return false;
  }

  if ( ! enchant_t::download_reforge( item, reforge_id ) )
  {
    item.sim -> errorf( "Player %s unable to parse reforge id %s for item \"%s\" at slot %s.\n", p -> name(), reforge_id.c_str(), item.name(), item.slot_name() );
    //return false;
  }

  if ( ! enchant_t::download_rsuffix( item, rsuffix_id ) )
  {
    item.sim -> errorf( "Player %s unable to determine random suffix '%s' for item '%s' at slot %s.\n", p -> name(), rsuffix_id.c_str(), item.name(), item.slot_name() );
    return false;
  }

  return true;
}
Example #6
0
bool wowhead_t::download_item( item_t&            item,
                               const std::string& item_id,
                               bool               ptr,
                               cache::behavior_t  caching )
{
  player_t* p = item.player;

  xml_node_t* node = download_id( item.sim, item_id, caching, ptr );
  if ( ! node )
  {
    if ( caching != cache::ONLY )
      item.sim -> errorf( "Player %s unable to download item id '%s'' from wowhead at slot %s.\n", p -> name(), item_id.c_str(), item.slot_name() );
    return false;
  }

  if ( ! parse_item_name( item, node ) )
  {
    item.sim -> errorf( "Player %s unable to determine item name for id '%s'' at slot %s.\n", p -> name(), item_id.c_str(), item.slot_name() );
    return false;
  }

  if ( ! parse_item_quality( item, node ) )
  {
    item.sim -> errorf( "Player %s unable to determine item quality for id '%s' at slot %s.\n", p -> name(), item_id.c_str(), item.slot_name() );
    return false;
  }

  if ( ! parse_item_level( item, node ) )
  {
    item.sim -> errorf( "Player %s unable to determine item level for id '%s' at slot %s.\n", p -> name(), item_id.c_str(), item.slot_name() );
    return false;
  }

  if ( ! parse_item_heroic( item, node ) )
  {
    item.sim -> errorf( "Player %s unable to determine heroic flag for id %s at slot %s.\n", p -> name(), item_id.c_str(), item.slot_name() );
    return false;
  }

  if ( ! parse_item_lfr( item, node ) )
  {
    item.sim -> errorf( "Player %s unable to determine LFR flag for id %s at slot %s.\n", p -> name(), item_id.c_str(), item.slot_name() );
    return false;
  }

  if ( ! parse_item_armor_type( item, node ) )
  {
    item.sim -> errorf( "Player %s unable to determine armor type for id %s at slot %s.\n", p -> name(), item_id.c_str(), item.slot_name() );
    return false;
  }

  if ( ! parse_item_stats( item, node ) )
  {
    item.sim -> errorf( "Player %s unable to determine stats for item '%s' at slot %s.\n", p -> name(), item.name(), item.slot_name() );
    return false;
  }

  if ( ! parse_weapon( item, node ) )
  {
    item.sim -> errorf( "Player %s unable to determine weapon info for item '%s' at slot %s.\n", p -> name(), item.name(), item.slot_name() );
    return false;
  }

  return true;
}