player_t* rawr_t::load_player( sim_t* sim, const std::string& character_file, const std::string& character_xml ) { xml_node_t* root_node = xml_t::create( sim, character_xml ); if ( ! root_node ) { sim -> errorf( "Unable to parse Rawr Character Save XML.\n" ); return 0; } if ( sim -> debug ) xml_t::print( root_node ); std::string class_str, race_str; if ( ! xml_t::get_value( class_str, root_node, "Class/." ) || ! xml_t::get_value( race_str, root_node, "Race/." ) ) { sim -> errorf( "Unable to determine character class and race in Rawr Character Save XML.\n" ); return 0; } std::string name_str; if ( ! xml_t::get_value( name_str, root_node, "Name/." ) ) { std::vector<std::string> tokens; int num_tokens = util_t::string_split( tokens, character_file, "\\/" ); assert( num_tokens > 0 ); name_str = tokens[ num_tokens-1 ]; } sim -> current_slot = 0; sim -> current_name = name_str; std::string talents_parm = class_str + "Talents/."; armory_t::format( name_str ); armory_t::format( class_str ); if ( class_str == "deathknight" ) class_str = "death_knight"; int race_type = translate_rawr_race_str( race_str ); player_t* p = player_t::create( sim, class_str, name_str, race_type ); sim -> active_player = p; if ( ! p ) { sim -> errorf( "Unable to build player with class '%s' and name '%s'.\n", class_str.c_str(), name_str.c_str() ); return 0; } p -> origin_str = character_file; xml_t::get_value( p -> region_str, root_node, "Region/." ); xml_t::get_value( p -> server_str, root_node, "Realm/." ); std::string talents_str; if ( ! xml_t::get_value( talents_str, root_node, talents_parm ) ) { sim -> errorf( "Player %s unable to determine character talents in Rawr Character Save XML.\n", p -> name() ); return 0; } std::string talents_encoding, glyphs_encoding; if ( 2 != util_t::string_split( talents_str, ".", "S S", &talents_encoding, &glyphs_encoding ) ) { sim -> errorf( "Player %s expected 'talents.glyphs' in Rawr Character Save XML, but found: %s\n", p -> name(), talents_str.c_str() ); return 0; } if ( ! p -> parse_talents_armory( talents_encoding ) ) { sim -> errorf( "Player %s unable to parse talent encoding '%s'.\n", p -> name(), talents_encoding.c_str() ); return 0; } p -> talents_str = "http://www.wowarmory.com/talent-calc.xml?cid="; p -> talents_str += util_t::class_id_string( p -> type ); p -> talents_str += "&tal=" + talents_encoding; p -> glyphs_str = ""; for ( int i=0; glyphs_encoding[ i ]; i++ ) { if ( glyphs_encoding[ i ] == '1' ) { const char* glyph_name = translate_glyph_name( p, i ); if ( ! glyph_name ) { sim -> errorf( "Player %s unable to parse glyph encoding '%s'.\n", p -> name(), glyphs_encoding.c_str() ); return 0; } if ( p -> glyphs_str.size() ) p -> glyphs_str += "/"; p -> glyphs_str += glyph_name; } } for ( int i=0; i < SLOT_MAX; i++ ) { sim -> current_slot = i; if( sim -> canceled ) return 0; const char* slot_name = translate_inventory_id( i ); if ( ! slot_name ) continue; item_t& item = p -> items[ i ]; std::string slot_encoding; if ( xml_t::get_value( slot_encoding, root_node, slot_name ) ) { std::string item_id, gem_ids[ 3 ], enchant_id; if ( 5 != util_t::string_split( slot_encoding, ".", "S S S S S", &item_id, &( gem_ids[ 0 ] ), &( gem_ids[ 1 ] ), &( gem_ids[ 2 ] ), &enchant_id ) ) { sim -> errorf( "Player %s unable to parse slot encoding '%s'.\n", p -> name(), slot_encoding.c_str() ); return 0; } bool success = item_t::download_slot( item, item_id, enchant_id, gem_ids ); if ( ! success ) { return 0; } } } return p; }
player_t* wowhead_t::download_player( sim_t* sim, const std::string& id, bool use_active_talents, cache::behavior_t caching ) { sim -> current_slot = 0; sim -> current_name = id; js_node_t* profile_js = download_profile( sim, id, caching ); if ( ! profile_js ) { sim -> errorf( "Unable to download character profile %s from wowhead.\n", id.c_str() ); return 0; } if ( sim -> debug ) js_t::print( profile_js, sim -> output_file ); std::string name_str; if ( ! js_t::get_value( name_str, profile_js, "name" ) ) { sim -> errorf( "Unable to extract player name from wowhead id '%s'.\n", id.c_str() ); name_str = "wowhead" + id; } sim -> current_name = name_str; util_t::format_text ( name_str, sim -> input_is_utf8 ); std::string level_str; if ( ! js_t::get_value( level_str, profile_js, "level" ) ) { sim -> errorf( "Unable to extract player level from wowhead id '%s'.\n", id.c_str() ); return 0; } int level = atoi( level_str.c_str() ); if ( level < 60 ) { level = 60; } else if ( level > 85 ) { level = 85; } std::string cid_str; if ( ! js_t::get_value( cid_str, profile_js, "classs" ) ) { sim -> errorf( "Unable to extract player class from wowhead id '%s'.\n", id.c_str() ); return 0; } int player_type = util_t::translate_class_id( atoi( cid_str.c_str() ) ); std::string type_str = util_t::player_type_string( player_type ); std::string rid_str; if ( ! js_t::get_value( rid_str, profile_js, "race" ) ) { sim -> errorf( "Unable to extract player race from wowhead id '%s'.\n", id.c_str() ); return 0; } race_type r = util_t::translate_race_id( atoi( rid_str.c_str() ) ); player_t* p = player_t::create( sim, type_str, name_str, r ); sim -> active_player = p; if ( ! p ) { sim -> errorf( "Unable to build player with class '%s' and name '%s' from wowhead id '%s'.\n", type_str.c_str(), name_str.c_str(), id.c_str() ); return 0; } p -> level = level; std::vector<std::string> region_data; int num_region = js_t::get_value( region_data, profile_js, "region" ); if ( num_region > 0 ) p -> region_str = region_data[ 0 ]; std::vector<std::string> realm_data; int num_realm = js_t::get_value( realm_data, profile_js, "realm" ); if ( num_realm > 0 ) p -> server_str = realm_data[ 0 ]; int user_id=0; if ( js_t::get_value( user_id, profile_js, "id" ) && ( user_id != 0 ) ) { p -> origin_str = "http://www.wowhead.com/profile=" + id; } else { std::string server_name = p -> server_str; std::string character_name = name_str; format_server( server_name ); armory_t::format( character_name, FORMAT_CHAR_NAME_MASK | FORMAT_ASCII_MASK ); p -> origin_str = "http://www.wowhead.com/profile=" + p -> region_str + "." + server_name + "." + character_name; } p -> professions_str = ""; for ( int i=0; i < PROFESSION_MAX; i++ ) { std::vector<std::string> skill_levels; if ( 2 == js_t::get_value( skill_levels, profile_js, translate_profession_id( i ) ) ) { if ( p -> professions_str.size() > 0 ) p -> professions_str += "/"; p -> professions_str += util_t::profession_type_string( i ); p -> professions_str += "="; p -> professions_str += skill_levels[ 0 ]; } } int active_talents = 0; js_t::get_value( active_talents, profile_js, "talents/active" ); if ( ! use_active_talents ) active_talents = ( active_talents ? 0 : 1 ); js_node_t* builds = js_t::get_node( profile_js, "talents/builds" ); if ( builds ) // !!! NEW FORMAT !!! { js_node_t* build = js_t::get_node( builds, ( active_talents ? "1" : "0" ) ); if ( ! build ) { sim -> errorf( "Player %s unable to access talent/glyph build from profile.\n", p -> name() ); return 0; } std::string talent_encoding; if ( ! js_t::get_value( talent_encoding, build, "talents" ) ) { sim -> errorf( "Player %s unable to access talent encoding from profile.\n", p -> name() ); return 0; } if ( ! p -> parse_talents_armory( talent_encoding ) ) { sim -> errorf( "Player %s unable to parse talent encoding '%s'.\n", p -> name(), talent_encoding.c_str() ); return 0; } p -> talents_str = "http://www.wowhead.com/talent#" + type_str + "-" + talent_encoding; std::string glyph_encoding; if ( ! js_t::get_value( glyph_encoding, build, "glyphs" ) ) { sim -> errorf( "Player %s unable to access glyph encoding from profile.\n", p -> name() ); return 0; } std::vector<std::string> glyph_ids; int num_glyphs = util_t::string_split( glyph_ids, glyph_encoding, ":" ); for ( int i=0; i < num_glyphs; i++ ) { std::string& glyph_id = glyph_ids[ i ]; if ( glyph_id == "0" ) continue; std::string glyph_name; if ( ! item_t::download_glyph( p, glyph_name, glyph_id ) ) { return 0; } if ( i ) p -> glyphs_str += "/"; p -> glyphs_str += glyph_name; } } else // !!! OLD FORMAT !!! { std::vector<std::string> talent_encodings; int num_builds = js_t::get_value( talent_encodings, profile_js, "talents/build" ); if ( num_builds == 2 ) { std::string& encoding = talent_encodings[ active_talents ]; if ( ! p -> parse_talents_armory( encoding ) ) { sim -> errorf( "Player %s unable to parse talent encoding '%s'.\n", p -> name(), encoding.c_str() ); return 0; } p -> talents_str = "http://www.wowhead.com/talent#" + type_str + "-" + encoding; } std::vector<std::string> glyph_encodings; num_builds = js_t::get_value( glyph_encodings, profile_js, "glyphs" ); if ( num_builds == 2 ) { p -> glyphs_str = ""; std::vector<std::string> glyph_ids; int num_glyphs = util_t::string_split( glyph_ids, glyph_encodings[ active_talents ], ":" ); for ( int i=0; i < num_glyphs; i++ ) { std::string& glyph_id = glyph_ids[ i ]; if ( glyph_id == "0" ) continue; std::string glyph_name; if ( ! item_t::download_glyph( p, glyph_name, glyph_id ) ) { return 0; } if ( i ) p -> glyphs_str += "/"; p -> glyphs_str += glyph_name; } } } for ( int i=0; i < SLOT_MAX; i++ ) { sim -> current_slot = i; if ( sim -> canceled ) return 0; std::vector<std::string> inventory_data; if ( js_t::get_value( inventory_data, profile_js, translate_inventory_id( i ) ) ) { std::string item_id = inventory_data[ 0 ]; std::string rsuffix_id = ( inventory_data[ 1 ] == "0" ) ? "" : inventory_data[ 1 ]; std::string enchant_id = inventory_data[ 2 ]; std::string gem_ids[ 3 ]; gem_ids[ 0 ] = inventory_data[ 4 ]; gem_ids[ 1 ] = inventory_data[ 5 ]; gem_ids[ 2 ] = inventory_data[ 6 ]; std::string addon_id; // WoWHead only supports an enchant OR tinker, both are in the enchant spot std::string reforge_id = inventory_data[ 8 ]; if ( item_id == "0" ) continue; // ignore empty slots if ( ! item_t::download_slot( p -> items[ i ], item_id, enchant_id, addon_id, reforge_id, rsuffix_id, gem_ids ) ) { return 0; } } } return p; }