void Reset()
    {
        events.Reset();
        ClearCastQueue();

        events.ScheduleEvent(EVENT_SHADOW_VOLLEY, 3000);
        events.ScheduleEvent(EVENT_CLEAVE, 5000);
        events.ScheduleEvent(EVENT_THUNDER_CLAP, urand(12000, 20000));
        events.ScheduleEvent(EVENT_VOID_BOLT, 30000);
        events.ScheduleEvent(EVENT_MARKOFKAZZAK, 25000);
        events.ScheduleEvent(EVENT_TWIST_REFLECT, 33000);

        events.ScheduleEvent(EVENT_ENRAGE, 60000);

        QueryResultAutoPtr resultWorldBossRespawn = QueryResultAutoPtr(NULL); 
        resultWorldBossRespawn = GameDataDatabase.PQuery("SELECT RespawnTime FROM worldboss_respawn WHERE BossEntry = %i", m_creature->GetEntry());
        if (resultWorldBossRespawn)
        {
            Field* fieldsWBR = resultWorldBossRespawn->Fetch();
            uint64 last_time_killed = fieldsWBR[0].GetUInt64();
            last_time_killed += 259200;
            if (last_time_killed >= time(0))
                me->DisappearAndDie();
        }
    }
/// Reconnect Challenge command handler
bool AuthSocket::_HandleReconnectChallenge()
{
    DEBUG_LOG("Entering _HandleReconnectChallenge");
    if (recv_len() < sizeof(sAuthLogonChallenge_C))
        return false;

    ///- Read the first 4 bytes (header) to get the length of the remaining of the packet
    std::vector<uint8> buf;
    buf.resize(4);

    recv((char *)&buf[0], 4);

    EndianConvert(*((uint16*)(buf[0])));
    uint16 remaining = ((sAuthLogonChallenge_C *)&buf[0])->size;
    DEBUG_LOG("[ReconnectChallenge] got header, body is %#04x bytes", remaining);

    if ((remaining < sizeof(sAuthLogonChallenge_C) - buf.size()) || (recv_len() < remaining))
        return false;

    //No big fear of memory outage (size is int16, i.e. < 65536)
    buf.resize(remaining + buf.size() + 1);
    buf[buf.size() - 1] = 0;
    sAuthLogonChallenge_C *ch = (sAuthLogonChallenge_C*)&buf[0];

    ///- Read the remaining of the packet
    recv((char *)&buf[4], remaining);
    DEBUG_LOG("[ReconnectChallenge] got full packet, %#04x bytes", ch->size);
    DEBUG_LOG("[ReconnectChallenge] name(%d): '%s'", ch->I_len, ch->I);

    _login = (const char*)ch->I;

    _safelogin = _login;
    AccountsDatabase.escape_string(_safelogin);

    EndianConvert(ch->build);
    _build = ch->build;

    QueryResultAutoPtr  result = AccountsDatabase.PQuery("SELECT session_key FROM account JOIN account_session ON account.account_id = account_session.account_id WHERE username = '******'", _safelogin.c_str());

    // Stop if the account is not found
    if (!result)
    {
        sLog.outLog(LOG_DEFAULT, "ERROR: [ERROR] user %s tried to login and we cannot find his session key in the database.", _login.c_str());
        close_connection();
        return false;
    }

    Field* fields = result->Fetch ();
    K.SetHexStr (fields[0].GetString ());

    ///- Sending response
    ByteBuffer pkt;
    pkt << uint8(CMD_AUTH_RECONNECT_CHALLENGE);
    pkt << uint8(0x00);
    _reconnectProof.SetRand(16 * 8);
    pkt.append(_reconnectProof.AsByteArray(16),16);         // 16 bytes random
    pkt << uint64(0x00) << uint64(0x00);                    // 16 bytes zeros
    send((char const*)pkt.contents(), pkt.size());
    return true;
}
Exemple #3
0
void WorldSession::HandlePetitionDeclineOpcode(WorldPacket & recv_data)
{
    CHECK_PACKET_SIZE(recv_data, 8);

    sLog.outDebug("Received opcode MSG_PETITION_DECLINE");  // ok
    //recv_data.hexlike();

    uint64 petitionguid;
    uint64 ownerguid;
    recv_data >> petitionguid;                              // petition guid
    sLog.outDebug("Petition %u declined by %u", GUID_LOPART(petitionguid), _player->GetGUIDLow());

    QueryResultAutoPtr result = RealmDataDatabase.PQuery("SELECT ownerguid FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid));
    if (!result)
        return;

    Field *fields = result->Fetch();
    ownerguid = MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER);

    Player *owner = sObjectMgr.GetPlayer(ownerguid);
    if (owner)                                               // petition owner online
    {
        WorldPacket data(MSG_PETITION_DECLINE, 8);
        data << _player->GetGUID();
        owner->SendPacketToSelf(&data);
    }
}
Exemple #4
0
void GuildMgr::LoadGuildAnnCooldowns()
{
    uint32 count = 0;

    QueryResultAutoPtr result = RealmDataDatabase.Query("SELECT guild_id, cooldown_end FROM guild_announce_cooldown");

    if (!result)
    {
        BarGoLink bar(1);

        bar.step();

        sLog.outString();
        sLog.outString(">> Loaded 0 guildann_cooldowns.");
        return;
    }

    BarGoLink bar(result->GetRowCount());

    do
    {
        Field *fields = result->Fetch();
        bar.step();

        uint32 guild_id       = fields[0].GetUInt32();
        uint64 respawn_time = fields[1].GetUInt64();

        m_guildCooldownTimes[guild_id] = time_t(respawn_time);

        ++count;
    } while (result->NextRow());

    sLog.outString(">> Loaded %u guild ann cooldowns.", m_guildCooldownTimes.size());
    sLog.outString();
}
Exemple #5
0
void WorldSession::SendPetitionQueryOpcode(uint64 petitionguid)
{
    uint64 ownerguid = 0;
    uint32 type;
    std::string name = "NO_NAME_FOR_GUID";
    uint8 signs = 0;

    QueryResultAutoPtr result = RealmDataDatabase.PQuery(
        "SELECT ownerguid, name, "
        "  (SELECT COUNT(playerguid) FROM petition_sign WHERE petition_sign.petitionguid = '%u') AS signs, "
        "  type "
        "FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid), GUID_LOPART(petitionguid));

    if (result)
    {
        Field* fields = result->Fetch();
        ownerguid = MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER);
        name      = fields[1].GetCppString();
        signs     = fields[2].GetUInt8();
        type      = fields[3].GetUInt32();
    }
    else
    {
        sLog.outDebug("CMSG_PETITION_QUERY failed for petition (GUID: %u)", GUID_LOPART(petitionguid));
        return;
    }

    WorldPacket data(SMSG_PETITION_QUERY_RESPONSE, (4+8+name.size()+1+1+4*13));
    data << GUID_LOPART(petitionguid);                      // guild/team guid (in Trinity always same as GUID_LOPART(petition guid)
    data << ownerguid;                                      // charter owner guid
    data << name;                                           // name (guild/arena team)
    data << uint8(0);                                       // 1
    if (type == 9)
    {
        data << uint32(9);
        data << uint32(9);
        data << uint32(0);                                  // bypass client - side limitation, a different value is needed here for each petition
    }
    else
    {
        data << type-1;
        data << type-1;
        data << type;                                       // bypass client - side limitation, a different value is needed here for each petition
    }
    data << uint32(0);                                      // 5
    data << uint32(0);                                      // 6
    data << uint32(0);                                      // 7
    data << uint32(0);                                      // 8
    data << uint16(0);                                      // 9 2 bytes field
    data << uint32(0);                                      // 10
    data << uint32(0);                                      // 11
    data << uint32(0);                                      // 13 count of next strings?
    data << uint32(0);                                      // 14
    if (type == 9)
        data << uint32(0);                                  // 15 0 - guild, 1 - arena team
    else
        data << uint32(1);
    SendPacket(&data);
}
Exemple #6
0
void MapManager::InitMaxInstanceId()
{
    i_MaxInstanceId = 0;

    QueryResultAutoPtr result = RealmDataDatabase.Query("SELECT MAX(id) FROM instance");
    if (result)
        i_MaxInstanceId = result->Fetch()[0].GetUInt32();
}
Exemple #7
0
void WorldSession::HandlePetitionShowSignOpcode(WorldPacket & recv_data)
{
    CHECK_PACKET_SIZE(recv_data, 8);

                                                            // ok
    sLog.outDebug("Received opcode CMSG_PETITION_SHOW_SIGNATURES");
    //recv_data.hexlike();

    uint8 signs = 0;
    uint64 petitionguid;
    recv_data >> petitionguid;                              // petition guid

    // solve (possible) some strange compile problems with explicit use GUID_LOPART(petitionguid) at some GCC versions (wrong code optimization in compiler?)
    uint32 petitionguid_low = GUID_LOPART(petitionguid);

    QueryResultAutoPtr result = RealmDataDatabase.PQuery("SELECT type FROM petition WHERE petitionguid = '%u'", petitionguid_low);
    if (!result)
    {
        sLog.outLog(LOG_DEFAULT, "ERROR: any petition on server...");
        return;
    }
    Field *fields = result->Fetch();
    uint32 type = fields[0].GetUInt32();

    // if guild petition and has guild => error, return;
    if (type==9 && _player->GetGuildId())
        return;

    result = RealmDataDatabase.PQuery("SELECT playerguid FROM petition_sign WHERE petitionguid = '%u'", petitionguid_low);

    // result==NULL also correct in case no sign yet
    if (result)
        signs = result->GetRowCount();

    sLog.outDebug("CMSG_PETITION_SHOW_SIGNATURES petition entry: '%u'", petitionguid_low);

    WorldPacket data(SMSG_PETITION_SHOW_SIGNATURES, (8+8+4+1+signs*12));
    data << petitionguid;                                   // petition guid
    data << _player->GetGUID();                             // owner guid
    data << petitionguid_low;                               // guild guid (in Trinity always same as GUID_LOPART(petitionguid)
    data << signs;                                          // sign's count

    for (uint8 i = 1; i <= signs; i++)
    {
        Field *fields2 = result->Fetch();
        uint64 plguid = fields2[0].GetUInt64();

        data << plguid;                                     // Player GUID
        data << (uint32)0;                                  // there 0 ...

        result->NextRow();
    }
    SendPacket(&data);
}
void WorldSession::HandleCharDeleteOpcode(WorldPacket & recv_data)
{
    CHECK_PACKET_SIZE(recv_data,8);

    uint64 guid;
    recv_data >> guid;

    // can't delete loaded character
    if (sObjectMgr.GetPlayer(guid))
        return;

    uint32 accountId = 0;
    std::string name;

    // is guild leader
    if (sGuildMgr.GetGuildByLeader(guid))
    {
        WorldPacket data(SMSG_CHAR_DELETE, 1);
        data << (uint8)CHAR_DELETE_FAILED_GUILD_LEADER;
        SendPacket(&data);
        return;
    }

    // is arena team captain
    if (sObjectMgr.GetArenaTeamByCaptain(guid))
    {
        WorldPacket data(SMSG_CHAR_DELETE, 1);
        data << (uint8)CHAR_DELETE_FAILED_ARENA_CAPTAIN;
        SendPacket(&data);
        return;
    }

    QueryResultAutoPtr result = RealmDataDatabase.PQuery("SELECT account,name FROM characters WHERE guid='%u'", GUID_LOPART(guid));
    if (result)
    {
        Field *fields = result->Fetch();
        accountId = fields[0].GetUInt32();
        name = fields[1].GetCppString();
    }

    // prevent deleting other players' characters using cheating tools
    if (accountId != GetAccountId())
        return;

    std::string IP_str = GetRemoteAddress();
    sLog.outDetail("Account: %d (IP: %s) Delete Character:[%s] (guid:%u)",GetAccountId(),IP_str.c_str(),name.c_str(),GUID_LOPART(guid));
    sLog.outLog(LOG_CHAR, "Account: %d (IP: %s) Delete Character:[%s] (guid: %u)",GetAccountId(),IP_str.c_str(),name.c_str(),GUID_LOPART(guid));

    Player::DeleteFromDB(guid, GetAccountId());

    WorldPacket data(SMSG_CHAR_DELETE, 1);
    data << (uint8)CHAR_DELETE_SUCCESS;
    SendPacket(&data);
}
Exemple #9
0
void ReputationMgr::LoadFromDB(QueryResultAutoPtr result)
{
    // Set initial reputations (so everything is nifty before DB data load)
    Initialize();

    //QueryResult *result = CharacterDatabase.PQuery("SELECT faction,standing,flags FROM character_reputation WHERE guid = '%u'",GetGUIDLow());

    if (result)
    {
        do
        {
            Field *fields = result->Fetch();

            FactionEntry const *factionEntry = sFactionStore.LookupEntry(fields[0].GetUInt32());
            if (factionEntry && (factionEntry->reputationListID >= 0))
            {
                FactionState* faction = &m_factions[factionEntry->reputationListID];

                // update standing to current
                faction->Standing = int32(fields[1].GetUInt32());

                uint32 dbFactionFlags = fields[2].GetUInt32();

                if (dbFactionFlags & FACTION_FLAG_VISIBLE)
                    SetVisible(faction);                    // have internal checks for forced invisibility

                if (dbFactionFlags & FACTION_FLAG_INACTIVE)
                    SetInactive(faction, true);             // have internal checks for visibility requirement

                if (dbFactionFlags & FACTION_FLAG_AT_WAR)   // DB at war
                    SetAtWar(faction, true);                // have internal checks for FACTION_FLAG_PEACE_FORCED
                else                                        // DB not at war
                {
                    // allow remove if visible (and then not FACTION_FLAG_INVISIBLE_FORCED or FACTION_FLAG_HIDDEN)
                    if (faction->Flags & FACTION_FLAG_VISIBLE)
                        SetAtWar(faction, false);           // have internal checks for FACTION_FLAG_PEACE_FORCED
                }

                // set atWar for hostile
                if (GetRank(factionEntry) <= REP_HOSTILE)
                    SetAtWar(faction,true);

                // reset changed flag if values similar to saved in DB
                if (faction->Flags==dbFactionFlags)
                {
                    faction->needSend = false;
                    faction->needSave = false;
                }
            }
        }
        while(result->NextRow());
    }
}
Exemple #10
0
void GuildMgr::LoadGuilds()
{
    Guild *newguild;
    uint32 count = 0;

    QueryResultAutoPtr result = RealmDataDatabase.Query("SELECT guildid FROM guild");

    if (!result)
    {

        BarGoLink bar(1);

        bar.step();

        sLog.outString();
        sLog.outString(">> Loaded %u guild definitions", count);
        return;
    }

    BarGoLink bar(result->GetRowCount());

    do
    {
        Field *fields = result->Fetch();

        bar.step();
        ++count;

        newguild = new Guild;
        if ( !newguild->LoadGuildFromDB( fields[0].GetUInt32() ) )
        {
            newguild->Disband();
            delete newguild;
            continue;
        }
        AddGuild(newguild);

    }
    while ( result->NextRow( ));


    result = RealmDataDatabase.Query("SELECT MAX(guildid) FROM guild");
    if (result)
        m_guildId = (*result)[0].GetUInt32()+1;

    sLog.outString();
    sLog.outString(">> Loaded %u guild definitions, next guild ID: %u", count, m_guildId);
}
Exemple #11
0
void WaypointMgr::UpdatePath(uint32 id)
{

    if (_waypointPathMap.find(id)!= _waypointPathMap.end())
        _waypointPathMap[id]->clear();

    QueryResultAutoPtr result = GameDataDatabase.PQuery("SELECT `id`,`point`,`position_x`,`position_y`,`position_z`,`move_type`,`delay`,`action`,`action_chance` FROM `waypoint_data` WHERE id = %u ORDER BY `point`", id);

    if (!result)
        return;

    WaypointPath* path_data;

    path_data = new WaypointPath;

    Field *fields;

    do
    {
        fields = result->Fetch();
        uint32 id = fields[0].GetUInt32();

        WaypointData *wp = new WaypointData;

        float x,y,z;
        x = fields[2].GetFloat();
        y = fields[3].GetFloat();
        z = fields[4].GetFloat();

        Looking4group::NormalizeMapCoord(x);
        Looking4group::NormalizeMapCoord(y);

        wp->id = fields[1].GetUInt32();
        wp->x = x;
        wp->y = y;
        wp->z = z;
        wp->moveType = WaypointMoveType(fields[5].GetUInt8());
        wp->delay = fields[6].GetUInt32();
        wp->event_id = fields[7].GetUInt32();
        wp->event_chance = fields[8].GetUInt8();

        path_data->push_back(wp);

    }
    while (result->NextRow());

   _waypointPathMap[id] = path_data;
}
Exemple #12
0
void WorldSession::HandleCharEnum(QueryResultAutoPtr result)
{
    // keys can be non cleared if player open realm list and close it by 'cancel'
    static SqlStatementID clearKeys;
    SqlStatement stmt = AccountsDatabase.CreateStatement(clearKeys, "UPDATE account_session SET v = '0', s = '0' WHERE account_id = ?");
    stmt.PExecute(GetAccountId());

    WorldPacket data(SMSG_CHAR_ENUM, 100);                  // we guess size

    uint8 num = 0;

    data << num;

    if (result)
    {
        do
        {
            uint32 guidlow = (*result)[0].GetUInt32();
            sLog.outDetail("Loading char guid %u from account %u.", guidlow, GetAccountId());

            if (Player::BuildEnumData(result, &data))
                ++num;
        }
        while (result->NextRow());
    }

    data.put<uint8>(0, num);

    SendPacket(&data);
}
Exemple #13
0
bool ChatHandler::HandleAccountWhispLogCommand(const char* args)
{
    if(!*args)
        return false;

    if (uint32 account_id = AccountMgr::GetId(args))
    {
        QueryResultAutoPtr result = AccountsDatabase.PQuery("SELECT account_flags FROM account WHERE account_id = '%u'", account_id);
        if (!result)
            return false;

        Field * fields = result->Fetch();

        uint64 accFlags = fields[0].GetUInt64();

        if (WorldSession *session = sWorld.FindSession(account_id))
        {
            if (accFlags & ACC_WHISPER_LOG)
                session->RemoveAccountFlag(ACC_WHISPER_LOG);
            else
                session->AddAccountFlag(ACC_WHISPER_LOG);
        }
        else
        {
            if (accFlags & ACC_WHISPER_LOG)
                WorldSession::SaveAccountFlags(account_id, accFlags &= ~ACC_WHISPER_LOG);
            else
                WorldSession::SaveAccountFlags(account_id, accFlags |= ACC_WHISPER_LOG);
        }

        if (accFlags & ACC_WHISPER_LOG)
            PSendSysMessage("WhispLog have been disabled for account: %u.", account_id);
        else
            PSendSysMessage("WhispLog have been enabled for account: %u.", account_id);
    }
    else
    {
        PSendSysMessage("Specified account not found.");
        SetSentErrorMessage(true);
        return false;
    }

    return true;
}
Exemple #14
0
void WorldSession::HandleChangePlayerNameOpcodeCallBack(QueryResultAutoPtr result, uint32 accountId, std::string newname)
{
    WorldSession * session = sWorld.FindSession(accountId);
    if (!session)
        return;

    if (!result)
    {
        WorldPacket data(SMSG_CHAR_RENAME, 1);
        data << uint8(CHAR_CREATE_ERROR);
        session->SendPacket(&data);
        return;
    }

    uint32 guidLow = result->Fetch()[0].GetUInt32();
    uint64 guid = MAKE_NEW_GUID(guidLow, 0, HIGHGUID_PLAYER);
    std::string oldname = result->Fetch()[1].GetCppString();

    static SqlStatementID changeCharName;
    static SqlStatementID deleteDeclinedName;

    RealmDataDatabase.BeginTransaction();

    SqlStatement stmt = RealmDataDatabase.CreateStatement(changeCharName, "UPDATE characters set name = ?, at_login = at_login & ~ ? WHERE guid = ?");
    stmt.addString(newname);
    stmt.addUInt32(uint32(AT_LOGIN_RENAME));
    stmt.addUInt32(guidLow);
    stmt.Execute();

    stmt = RealmDataDatabase.CreateStatement(deleteDeclinedName, "DELETE FROM character_declinedname WHERE guid = ?");
    stmt.PExecute(guidLow);

    RealmDataDatabase.CommitTransaction();

    sLog.outLog(LOG_CHAR, "Account: %d (IP: %s) Character:[%s] (guid:%u) Changed name to: %s", session->GetAccountId(), session->GetRemoteAddress().c_str(), oldname.c_str(), guidLow, newname.c_str());

    WorldPacket data(SMSG_CHAR_RENAME, 1+8+(newname.size()+1));
    data << uint8(RESPONSE_SUCCESS);
    data << uint64(guid);
    data << newname;
    session->SendPacket(&data);
}
Exemple #15
0
/// Display info on users currently in the realm
bool ChatHandler::HandleAccountOnlineListCommand(const char* args)
{
    ///- Get the list of accounts ID logged to the realm
    QueryResultAutoPtr resultDB = RealmDataDatabase.Query("SELECT name, account FROM characters WHERE online > 0");
    if (!resultDB)
        return true;

    ///- Display the list of account/characters online
    SendSysMessage("=====================================================================");
    SendSysMessage(LANG_ACCOUNT_LIST_HEADER);
    SendSysMessage("=====================================================================");

    ///- Circle through accounts
    do
    {
        Field *fieldsDB = resultDB->Fetch();
        std::string name = fieldsDB[0].GetCppString();
        uint32 account = fieldsDB[1].GetUInt32();

        ///- Get the username, last IP and GM level of each account
        // No SQL injection. account is uint32.
        //                                                                  0         1          2              3
        QueryResultAutoPtr resultLogin = AccountsDatabase.PQuery("SELECT username, last_ip, permission_mask, expansion_id "
                                                                 "FROM account JOIN account_permissions ON account.account_id = account_permissions.account_id "
                                                                 "WHERE account_id = '%u' AND realm_id = '%u'", account, realmID);

        if(resultLogin)
        {
            Field *fieldsLogin = resultLogin->Fetch();
            PSendSysMessage("|%15s| %20s | %15s |%4d|%5d|",
                fieldsLogin[0].GetString(),name.c_str(),fieldsLogin[1].GetString(),fieldsLogin[2].GetUInt32(),fieldsLogin[3].GetUInt32());
        }
        else
            PSendSysMessage(LANG_ACCOUNT_LIST_ERROR, name.c_str());

    }
    while(resultDB->NextRow());

    SendSysMessage("=====================================================================");
    return true;
}
Exemple #16
0
    void Reset()
    {
        Enrage_Timer    = 0;
        Armor_Timer     = 5000 + rand()%8000;
        Chain_Timer     = 10000 + rand()%20000;
        Quake_Timer     = 25000 + rand()%10000;
        Overrun_Timer   = 30000 + rand()%15000;

        InEnrage = false;

        QueryResultAutoPtr resultWorldBossRespawn = QueryResultAutoPtr(NULL); 
        resultWorldBossRespawn = GameDataDatabase.PQuery("SELECT RespawnTime FROM worldboss_respawn WHERE BossEntry = %i", m_creature->GetEntry());
        if (resultWorldBossRespawn)
        {
            Field* fieldsWBR = resultWorldBossRespawn->Fetch();
            uint64 last_time_killed = fieldsWBR[0].GetUInt64();
            last_time_killed += 259200;
            if (last_time_killed >= time(0))
                me->DisappearAndDie();
        }
        
    }
void LoadRandomEnchantmentsTable()
{
    RandomItemEnch.clear();                                 // for reload case

    EnchantmentStore::iterator tab;
    uint32 entry, ench;
    float chance;
    uint32 count = 0;

    QueryResultAutoPtr result = GameDataDatabase.Query("SELECT entry, ench, chance FROM item_enchantment_template");

    if (result)
    {
        BarGoLink bar(result->GetRowCount());

        do
        {
            Field *fields = result->Fetch();
            bar.step();

            entry = fields[0].GetUInt32();
            ench = fields[1].GetUInt32();
            chance = fields[2].GetFloat();

            if (chance > 0.000001f && chance <= 100.0f)
                RandomItemEnch[entry].push_back(EnchStoreItem(ench, chance));

            ++count;
        } while (result->NextRow());

        sLog.outString();
        sLog.outString(">> Loaded %u Item Enchantment definitions", count);
    }
    else
    {
        sLog.outString();
        sLog.outLog(LOG_DB_ERR, ">> Loaded 0 Item Enchantment definitions. DB table `item_enchantment_template` is empty.");
    }
}
Exemple #18
0
bool Corpse::LoadFromDB(uint32 guid, QueryResultAutoPtr result, uint32 InstanceId)
{
    if (! result)
        //                                        0          1          2          3           4   5    6    7           8
        result = RealmDataDatabase.PQuery("SELECT position_x,position_y,position_z,orientation,map,data,time,corpse_type,instance FROM corpse WHERE guid = '%u'",guid);

    if (! result)
    {
        sLog.outLog(LOG_DEFAULT, "ERROR: Corpse (GUID: %u) not found in table `corpse`, can't load. ",guid);
        return false;
    }

    Field *fields = result->Fetch();

    if (!LoadFromDB(guid,fields))
        return false;

    return true;
}
Exemple #19
0
void PoolManager::LoadFromDB()
{
    QueryResultAutoPtr result = GameDataDatabase.Query("SELECT MAX(entry) FROM pool_template");
    if (!result)
    {
        sLog.outString(">> Table pool_template is empty.");
        sLog.outString();
        return;
    }
    else
    {
        Field *fields = result->Fetch();
        max_pool_id = fields[0].GetUInt16();
    }

    mPoolTemplate.resize(max_pool_id + 1);

    result = GameDataDatabase.Query("SELECT entry,max_limit FROM pool_template");
    if (!result)
    {
        mPoolTemplate.clear();
        sLog.outString(">> Table pool_template is empty:");
        sLog.outString();
        return;
    }

    uint32 count = 0;

    BarGoLink bar((int)result->GetRowCount());
    do
    {
        ++count;
        Field *fields = result->Fetch();

        bar.step();

        uint16 pool_id = fields[0].GetUInt16();

        PoolTemplateData& pPoolTemplate = mPoolTemplate[pool_id];
        pPoolTemplate.MaxLimit  = fields[1].GetUInt32();
        pPoolTemplate.AutoSpawn = true;          // will update and later data loading

    } while (result->NextRow());

    sLog.outString();
    sLog.outString( ">> Loaded %u objects pools", count );

    PoolMapChecker mapChecker;

    // Creatures

    mPoolCreatureGroups.resize(max_pool_id + 1);
    mCreatureSearchMap.clear();
    //                                   1     2           3
    result = GameDataDatabase.Query("SELECT guid, pool_entry, chance FROM pool_creature");

    count = 0;
    if (!result)
    {
        BarGoLink bar2(1);
        bar2.step();

        sLog.outString();
        sLog.outString(">> Loaded %u creatures in pools", count );
    }
    else
    {

        BarGoLink bar2((int)result->GetRowCount());
        do
        {
            Field *fields = result->Fetch();

            bar2.step();

            uint32 guid    = fields[0].GetUInt32();
            uint16 pool_id = fields[1].GetUInt16();
            float chance   = fields[2].GetFloat();

            CreatureData const* data = sObjectMgr.GetCreatureData(guid);
            if (!data)
            {
                sLog.outLog(LOG_DB_ERR, "`pool_creature` has a non existing creature spawn (GUID: %u) defined for pool id (%u), skipped.", guid, pool_id );
                continue;
            }
            if (pool_id > max_pool_id)
            {
                sLog.outLog(LOG_DB_ERR, "`pool_creature` pool id (%i) is out of range compared to max pool id in `pool_template`, skipped.",pool_id);
                continue;
            }
            if (chance < 0 || chance > 100)
            {
                sLog.outLog(LOG_DB_ERR, "`pool_creature` has an invalid chance (%f) for creature guid (%u) in pool id (%i), skipped.", chance, guid, pool_id);
                continue;
            }

            if (!mapChecker.CheckAndRemember(data->mapid, pool_id, "pool_creature", "creature guid"))
                continue;

            PoolTemplateData *pPoolTemplate = &mPoolTemplate[pool_id];
            ++count;

            PoolObject plObject = PoolObject(guid, chance);
            PoolGroup<Creature>& cregroup = mPoolCreatureGroups[pool_id];
            cregroup.SetPoolId(pool_id);
            cregroup.AddEntry(plObject, pPoolTemplate->MaxLimit);
            SearchPair p(guid, pool_id);
            mCreatureSearchMap.insert(p);

        } while (result->NextRow());
        sLog.outString();
        sLog.outString( ">> Loaded %u creatures in pools", count );
    }

    // Gameobjects

    mPoolGameobjectGroups.resize(max_pool_id + 1);
    mGameobjectSearchMap.clear();
    //                                   1     2           3
    result = GameDataDatabase.Query("SELECT guid, pool_entry, chance FROM pool_gameobject");

    count = 0;
    if (!result)
    {
        BarGoLink bar2(1);
        bar2.step();

        sLog.outString();
        sLog.outString(">> Loaded %u gameobject in pools", count );
    }
    else
    {

        BarGoLink bar2((int)result->GetRowCount());
        do
        {
            Field *fields = result->Fetch();

            bar2.step();

            uint32 guid    = fields[0].GetUInt32();
            uint16 pool_id = fields[1].GetUInt16();
            float chance   = fields[2].GetFloat();

            GameObjectData const* data = sObjectMgr.GetGOData(guid);
            if (!data)
            {
                sLog.outLog(LOG_DB_ERR, "`pool_gameobject` has a non existing gameobject spawn (GUID: %u) defined for pool id (%u), skipped.", guid, pool_id );
                continue;
            }
            GameObjectInfo const* goinfo = ObjectMgr::GetGameObjectInfo(data->id);
            if (goinfo->type != GAMEOBJECT_TYPE_CHEST &&
                    goinfo->type != GAMEOBJECT_TYPE_GOOBER &&
                    goinfo->type != GAMEOBJECT_TYPE_FISHINGHOLE)
            {
                sLog.outLog(LOG_DB_ERR, "`pool_gameobject` has a not lootable gameobject spawn (GUID: %u, type: %u) defined for pool id (%u), skipped.", guid, goinfo->type, pool_id );
                continue;
            }
            if (pool_id > max_pool_id)
            {
                sLog.outLog(LOG_DB_ERR, "`pool_gameobject` pool id (%i) is out of range compared to max pool id in `pool_template`, skipped.",pool_id);
                continue;
            }
            if (chance < 0 || chance > 100)
            {
                sLog.outLog(LOG_DB_ERR, "`pool_gameobject` has an invalid chance (%f) for gameobject guid (%u) in pool id (%i), skipped.", chance, guid, pool_id);
                continue;
            }

            if (!mapChecker.CheckAndRemember(data->mapid, pool_id, "pool_gameobject", "gameobject guid"))
                continue;

            PoolTemplateData *pPoolTemplate = &mPoolTemplate[pool_id];

            ++count;

            PoolObject plObject = PoolObject(guid, chance);
            PoolGroup<GameObject>& gogroup = mPoolGameobjectGroups[pool_id];
            gogroup.SetPoolId(pool_id);
            gogroup.AddEntry(plObject, pPoolTemplate->MaxLimit);
            SearchPair p(guid, pool_id);
            mGameobjectSearchMap.insert(p);

        } while( result->NextRow() );
        sLog.outString();
        sLog.outString( ">> Loaded %u gameobject in pools", count );
    }

    // Pool of pools
    mPoolPoolGroups.resize(max_pool_id + 1);
    //                                   1        2            3
    result = GameDataDatabase.Query("SELECT pool_id, mother_pool, chance FROM pool_pool");

    count = 0;
    if( !result )
    {
        BarGoLink bar2(1);
        bar2.step();

        sLog.outString();
        sLog.outString(">> Loaded %u pools in pools", count );
    }
    else
    {

        BarGoLink bar2( (int)result->GetRowCount() );
        do
        {
            Field *fields = result->Fetch();

            bar2.step();

            uint16 child_pool_id  = fields[0].GetUInt16();
            uint16 mother_pool_id = fields[1].GetUInt16();
            float chance          = fields[2].GetFloat();

            if (mother_pool_id > max_pool_id)
            {
                sLog.outLog(LOG_DB_ERR, "`pool_pool` mother_pool id (%i) is out of range compared to max pool id in `pool_template`, skipped.",mother_pool_id);
                continue;
            }
            if (child_pool_id > max_pool_id)
            {
                sLog.outLog(LOG_DB_ERR, "`pool_pool` included pool_id (%i) is out of range compared to max pool id in `pool_template`, skipped.",child_pool_id);
                continue;
            }
            if (mother_pool_id == child_pool_id)
            {
                sLog.outLog(LOG_DB_ERR, "`pool_pool` pool_id (%i) includes itself, dead-lock detected, skipped.",child_pool_id);
                continue;
            }
            if (chance < 0 || chance > 100)
            {
                sLog.outLog(LOG_DB_ERR, "`pool_pool` has an invalid chance (%f) for pool id (%u) in mother pool id (%i), skipped.", chance, child_pool_id, mother_pool_id);
                continue;
            }

            PoolTemplateData *pPoolTemplateMother = &mPoolTemplate[mother_pool_id];

            ++count;

            PoolObject plObject = PoolObject(child_pool_id, chance);
            PoolGroup<Pool>& plgroup = mPoolPoolGroups[mother_pool_id];
            plgroup.SetPoolId(mother_pool_id);
            plgroup.AddEntry(plObject, pPoolTemplateMother->MaxLimit);
            SearchPair p(child_pool_id, mother_pool_id);
            mPoolSearchMap.insert(p);

            // update top independent pool flag
            mPoolTemplate[child_pool_id].AutoSpawn = false;

        } while( result->NextRow() );

        // Now check for circular reference
        for(uint16 i=0; i<max_pool_id; ++i)
        {
            std::set<uint16> checkedPools;
            for(SearchMap::iterator poolItr = mPoolSearchMap.find(i); poolItr != mPoolSearchMap.end(); poolItr = mPoolSearchMap.find(poolItr->second))
            {
                // if child pool not have map data then it empty or have not checked child then will checked and all line later
                if (MapEntry const* childMapEntry = mapChecker.GetPoolMapEntry(poolItr->first))
                {
                    if (!mapChecker.CheckAndRemember(childMapEntry->MapID, poolItr->second, "pool_pool", "pool with creature/gameobject"))
                    {
                        mPoolPoolGroups[poolItr->second].RemoveOneRelation(poolItr->first);
                        mPoolSearchMap.erase(poolItr);
                        --count;
                        break;
                    }
                }

                checkedPools.insert(poolItr->first);
                if(checkedPools.find(poolItr->second) != checkedPools.end())
                {
                    std::ostringstream ss;
                    ss<< "The pool(s) ";
                    for (std::set<uint16>::const_iterator itr=checkedPools.begin(); itr!=checkedPools.end(); ++itr)
                        ss << *itr << " ";
                    ss << "create(s) a circular reference, which can cause the server to freeze.\nRemoving the last link between mother pool "
                       << poolItr->first << " and child pool " << poolItr->second;
                    sLog.outLog(LOG_DB_ERR, "%s", ss.str().c_str());
                    mPoolPoolGroups[poolItr->second].RemoveOneRelation(poolItr->first);
                    mPoolSearchMap.erase(poolItr);
                    --count;
                    break;
                }
            }
        }

        sLog.outString();
        sLog.outString( ">> Loaded %u pools in mother pools", count );
    }
}
Exemple #20
0
void WorldSession::HandleSendMail(WorldPacket & recv_data)
{
    CHECK_PACKET_SIZE(recv_data,8+1+1+1+4+4+1+4+4+8+1);

    ObjectGuid mailboxGuid;
    uint64 unk3;
    std::string receiver, subject, body;
    uint32 unk1, unk2, money, COD;
    uint8 unk4;
    recv_data >> mailboxGuid;
    recv_data >> receiver;

    // recheck
    CHECK_PACKET_SIZE(recv_data, 8+(receiver.size()+1)+1+1+4+4+1+4+4+8+1);

    recv_data >> subject;

    // recheck
    CHECK_PACKET_SIZE(recv_data, 8+(receiver.size()+1)+(subject.size()+1)+1+4+4+1+4+4+8+1);

    recv_data >> body;

    // recheck
    CHECK_PACKET_SIZE(recv_data, 8+(receiver.size()+1)+(subject.size()+1)+(body.size()+1)+4+4+1+4+4+8+1);

    recv_data >> unk1;                                      // stationery?
    recv_data >> unk2;                                      // 0x00000000

    uint8 items_count;
    recv_data >> items_count;                               // attached items count

    if (items_count > MAX_MAIL_ITEMS)                       // client limit
    {
        GetPlayer()->SendMailResult(0, MAIL_SEND, MAIL_ERR_TOO_MANY_ATTACHMENTS);
        recv_data.rpos(recv_data.wpos());                   // set to end to avoid warnings spam
        return;
    }

    // recheck
    CHECK_PACKET_SIZE(recv_data, 8+(receiver.size()+1)+(subject.size()+1)+(body.size()+1)+4+4+1+items_count*(1+8)+4+4+8+1);

    ObjectGuid itemGuids[MAX_MAIL_ITEMS];

    for (uint8 i = 0; i < items_count; ++i)
    {
        recv_data.read_skip<uint8>();                       // item slot in mail, not used
        recv_data >> itemGuids[i];
    }

    recv_data >> money >> COD;                              // money and cod
    recv_data >> unk3;                                      // const 0
    recv_data >> unk4;                                      // const 0

    // packet read complete, now do check

    if (!CheckMailBox(mailboxGuid))
        return;

    items_count = 0;
    // remove duplicates, after this items_count will contains real items count
    {
        ObjectGuid tmpItemGuids[MAX_MAIL_ITEMS];
        bool inTable = false;
        for (uint8 i = 0; i < MAX_MAIL_ITEMS; ++i)
        {
            if (itemGuids[i].IsEmpty())
                continue;

            inTable = false;

            for (uint8 j = 0; j < MAX_MAIL_ITEMS; ++j)
            {
                if (tmpItemGuids[j].IsEmpty())
                    break;

                if (tmpItemGuids[j] == itemGuids[i])
                {
                    inTable = true;
                    break;
                }
            }

            if (!inTable)
            {
                tmpItemGuids[items_count] = itemGuids[i];
                ++items_count;
            }

            itemGuids[i].Clear();
        }

        for (uint8 i = 0; i < items_count; ++i)
            itemGuids[i] = tmpItemGuids[i];
    }

    if (receiver.empty())
        return;

    Player* pl = _player;

    ObjectGuid rc;
    if (normalizePlayerName(receiver))
        rc = sObjectMgr.GetPlayerGUIDByName(receiver);

    if (!rc)
    {
        sLog.outDetail("Player %u is sending mail to %s (GUID: not existed!) with subject %s and body %s includes %u items, %u copper and %u COD copper with unk1 = %u, unk2 = %u",
            pl->GetGUIDLow(), receiver.c_str(), subject.c_str(), body.c_str(), items_count, money, COD, unk1, unk2);
        pl->SendMailResult(0, 0, MAIL_ERR_RECIPIENT_NOT_FOUND);
        return;
    }

    sLog.outDetail("Player %u is sending mail to %s (GUID: %u) with subject %s and body %s includes %u items, %u copper and %u COD copper with unk1 = %u, unk2 = %u", pl->GetGUIDLow(), receiver.c_str(), GUID_LOPART(rc), subject.c_str(), body.c_str(), items_count, money, COD, unk1, unk2);

    if (pl->GetGUID() == rc)
    {
        pl->SendMailResult(0, 0, MAIL_ERR_CANNOT_SEND_TO_SELF);
        return;
    }

    uint32 reqmoney = money + 30;
    if (items_count)
        reqmoney = money + (30 * items_count);

    if (pl->GetMoney() < reqmoney)
    {
        pl->SendMailResult(0, 0, MAIL_ERR_NOT_ENOUGH_MONEY);
        return;
    }

    Player *receive = sObjectMgr.GetPlayer(rc);

    uint32 rc_team = 0;
    uint8 mails_count = 0;                                  //do not allow to send to one player more than 100 mails

    if (receive)
    {
        rc_team = receive->GetTeam();
        mails_count = receive->GetMailSize();
    }
    else
    {
        rc_team = sObjectMgr.GetPlayerTeamByGUID(rc);
        QueryResultAutoPtr result = RealmDataDatabase.PQuery("SELECT COUNT(*) FROM mail WHERE receiver = '%u'", GUID_LOPART(rc));
        if (result)
        {
            Field *fields = result->Fetch();
            mails_count = fields[0].GetUInt32();
        }
    }

    //do not allow to have more than 100 mails in mailbox.. mails count is in opcode uint8!!! - so max can be 255..
    if (mails_count > 100)
    {
        pl->SendMailResult(0, 0, MAIL_ERR_INTERNAL_ERROR);
        return;
    }

    // test the receiver's Faction...
    if (!sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_MAIL) && pl->GetTeam() != rc_team && !HasPermissions(PERM_GMT))
    {
        pl->SendMailResult(0, 0, MAIL_ERR_NOT_YOUR_TEAM);
        return;
    }

    Item* items[MAX_MAIL_ITEMS];

    for(uint8 i = 0; i < items_count; ++i)
    {
        if (!itemGuids[i].IsItem())
        {
            pl->SendMailResult(0, MAIL_SEND, MAIL_ERR_MAIL_ATTACHMENT_INVALID);
            return;
        }

        if (!itemGuids[i].GetCounter())
        {
            pl->SendMailResult(0, 0, MAIL_ERR_INTERNAL_ERROR);
            return;
        }

        Item* item = pl->GetItemByGuid(itemGuids[i]);

        // prevent sending bag with items (cheat: can be placed in bag after adding equipped empty bag to mail)
        if(!item)
        {
            pl->SendMailResult(0, MAIL_SEND, MAIL_ERR_MAIL_ATTACHMENT_INVALID);
            return;
        }

        if (!item->CanBeTraded())
        {
            pl->SendMailResult(0, MAIL_SEND, MAIL_ERR_EQUIP_ERROR, EQUIP_ERR_MAIL_BOUND_ITEM);
            return;
        }

        if ((item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAGS_CONJURED) || item->GetUInt32Value(ITEM_FIELD_DURATION)))
        {
            pl->SendMailResult(0, MAIL_SEND, MAIL_ERR_EQUIP_ERROR, EQUIP_ERR_MAIL_BOUND_ITEM);
            return;
        }

        if (COD && item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAGS_WRAPPED))
        {
            pl->SendMailResult(0, MAIL_SEND, MAIL_ERR_CANT_SEND_WRAPPED_COD);
            return;
        }

        if (item->IsBag() && !((Bag*)item)->IsEmpty())
        {
            pl->SendMailResult(0, 0, MAIL_ERR_INTERNAL_ERROR);
            return;
        }

        items[i] = item;
    }

    pl->SendMailResult(0, MAIL_SEND, MAIL_OK);

    pl->ModifyMoney(-int32(reqmoney));

    bool needItemDelay = false;

    MailDraft draft(subject, body);

    uint32 rc_account = 0;
    if (receive)
        rc_account = receive->GetSession()->GetAccountId();
    else
        rc_account = sObjectMgr.GetPlayerAccountIdByGUID(rc);

    if (items_count > 0 || money > 0)
    {
        if (items_count > 0)
        {
            for(uint8 i = 0; i < items_count; ++i)
            {
                Item* item = items[i];
                if (!item)
                    continue;

                if (HasPermissions(PERM_GMT) && sWorld.getConfig(CONFIG_GM_LOG_TRADE))
                {
                    sLog.outCommand(GetAccountId(), "GM %s (Account: %u) mail item: %s (Entry: %u Count: %u) to player: %s (Account: %u)",
                        GetPlayerName(), GetAccountId(), item->GetProto()->Name1, item->GetEntry(), item->GetCount(), receiver.c_str(), rc_account);
                }

                sLog.outLog(LOG_TRADE, "Player %s (Account: %u) mail item: %s (Entry: %u Count: %u) to player: %s (Account: %u)",
                    GetPlayerName(), GetAccountId(), item->GetProto()->Name1, item->GetEntry(), item->GetCount(), receiver.c_str(), rc_account);

                pl->MoveItemFromInventory(item->GetBagSlot(), item->GetSlot(), true);
                RealmDataDatabase.BeginTransaction();
                item->DeleteFromInventoryDB();     //deletes item from character's inventory
                item->SaveToDB();                  // recursive and not have transaction guard into self, item not in inventory and can be save standalone
                // owner in data will set at mail receive and item extracting
                RealmDataDatabase.PExecute("UPDATE item_instance SET owner_guid = '%u' WHERE guid='%u'", rc.GetCounter(), item->GetGUIDLow());
                RealmDataDatabase.CommitTransaction();

                draft.AddItem(item);
            }

            // if item send to character at another account, then apply item delivery delay
            needItemDelay = pl->GetSession()->GetAccountId() != rc_account;
        }

        if (money > 0)
        {
            if (HasPermissions(PERM_GMT) && sWorld.getConfig(CONFIG_GM_LOG_TRADE))
            {
                sLog.outCommand(GetAccountId(),"GM %s (Account: %u) mail money: %u to player: %s (Account: %u)",
                    GetPlayerName(), GetAccountId(), money, receiver.c_str(), rc_account);
            }

            if (_player->GetSession()->IsAccountFlagged(ACC_SPECIAL_LOG))
            {
                sLog.outLog(LOG_SPECIAL, "Player %s (Account: %u) mail money: %u to player: %s (Account: %u)",
                    GetPlayerName(), GetAccountId(), money, receiver.c_str(), rc_account);
            }

            sLog.outLog(LOG_TRADE, "Player %s (Account: %u) mail money: %u to player: %s (Account: %u)",
                GetPlayerName(), GetAccountId(), money, receiver.c_str(), rc_account);
        }
    }

    sLog.outLog(LOG_MAIL, "Player %s (Account: %u) sent mail to player: %s (Account: %u) with subject: %s and body: %s",
        GetPlayerName(), GetAccountId(), receiver.c_str(), rc_account, subject.c_str(), body.c_str());

    // If theres is an item, there is a one hour delivery delay if sent to another account's character.
    uint32 deliver_delay = needItemDelay ? sWorld.getConfig(CONFIG_MAIL_DELIVERY_DELAY) : 0;

    // If GM sends mail to player - deliver_delay must be zero
    if (deliver_delay && HasPermissions(PERM_GMT) && sWorld.getConfig(CONFIG_GM_MAIL))
        deliver_delay = 0;

    // will delete item or place to receiver mail list
    draft
        .SetMoney(money)
        .SetCOD(COD)
        .SendMailTo(MailReceiver(receive, rc), pl, body.empty() ? MAIL_CHECK_MASK_COPIED : MAIL_CHECK_MASK_HAS_BODY, deliver_delay);

    RealmDataDatabase.BeginTransaction();
    pl->SaveInventoryAndGoldToDB();
    RealmDataDatabase.CommitTransaction();
}
Exemple #21
0
void WorldSession::HandleTurnInPetitionOpcode(WorldPacket & recv_data)
{
    CHECK_PACKET_SIZE(recv_data, 8);

    sLog.outDebug("Received opcode CMSG_TURN_IN_PETITION"); // ok
    //recv_data.hexlike();

    WorldPacket data;
    uint64 petitionguid;

    uint32 ownerguidlo;
    uint32 type;
    std::string name;

    recv_data >> petitionguid;

    sLog.outDebug("Petition %u turned in by %u", GUID_LOPART(petitionguid), _player->GetGUIDLow());

    // data
    QueryResultAutoPtr result = RealmDataDatabase.PQuery("SELECT ownerguid, name, type FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid));
    if (result)
    {
        Field *fields = result->Fetch();
        ownerguidlo = fields[0].GetUInt32();
        name = fields[1].GetCppString();
        type = fields[2].GetUInt32();
    }
    else
    {
        sLog.outLog(LOG_DEFAULT, "ERROR: petition table has broken data!");
        return;
    }

    if (type == 9)
    {
        if (_player->GetGuildId())
        {
            data.Initialize(SMSG_TURN_IN_PETITION_RESULTS, 4);
            data << (uint32)PETITION_TURN_ALREADY_IN_GUILD; // already in guild
            _player->SendPacketToSelf(&data);
            return;
        }
    }
    else
    {
        uint8 slot = ArenaTeam::GetSlotByType(type);
        if (slot >= MAX_ARENA_SLOT)
            return;

        if (_player->GetArenaTeamId(slot))
        {
            //data.Initialize(SMSG_TURN_IN_PETITION_RESULTS, 4);
            //data << (uint32)PETITION_TURN_ALREADY_IN_GUILD;                          // already in guild
            //_player->BroadcastPacketToSelf(&data);
            SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ALREADY_IN_ARENA_TEAM);
            return;
        }
    }

    if (_player->GetGUIDLow() != ownerguidlo)
        return;

    // signs
    uint8 signs;
    result = RealmDataDatabase.PQuery("SELECT playerguid FROM petition_sign WHERE petitionguid = '%u'", GUID_LOPART(petitionguid));
    if (result)
        signs = result->GetRowCount();
    else
        signs = 0;

    uint32 count;
    //if(signs < sWorld.getConfig(CONFIG_MIN_PETITION_SIGNS))
    if (type == 9)
        count = sWorld.getConfig(CONFIG_MIN_PETITION_SIGNS);
    else
        count = type-1;
    if (signs < count)
    {
        data.Initialize(SMSG_TURN_IN_PETITION_RESULTS, 4);
        data << (uint32)PETITION_TURN_NEED_MORE_SIGNATURES; // need more signatures...
        SendPacket(&data);
        return;
    }

    if (type == 9)
    {
        if (sGuildMgr.GetGuildByName(name))
        {
            SendGuildCommandResult(GUILD_CREATE_S, name, GUILD_NAME_EXISTS);
            return;
        }
    }
    else
    {
        if (sObjectMgr.GetArenaTeamByName(name))
        {
            SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ARENA_TEAM_NAME_EXISTS_S);
            return;
        }
    }

    // and at last charter item check
    Item *item = _player->GetItemByGuid(petitionguid);
    if (!item)
        return;

    // OK!

    // delete charter item
    _player->DestroyItem(item->GetBagSlot(),item->GetSlot(), true);

    if (type == 9)                                           // create guild
    {
        Guild* guild = new Guild;
        if (!guild->create(_player->GetGUID(), name))
        {
            delete guild;
            return;
        }

        // register guild and add guildmaster
        sGuildMgr.AddGuild(guild);

        // add members
        for (uint8 i = 0; i < signs; ++i)
        {
            Field* fields = result->Fetch();
            guild->AddMember(fields[0].GetUInt64(), guild->GetLowestRank());
            result->NextRow();
        }
    }
    else                                                    // or arena team
    {
        ArenaTeam* at = new ArenaTeam;
        if (!at->Create(_player->GetGUID(), type, name))
        {
            sLog.outLog(LOG_DEFAULT, "ERROR: PetitionsHandler: arena team create failed.");
            delete at;
            return;
        }

        CHECK_PACKET_SIZE(recv_data, 8+5*4);
        uint32 icon, iconcolor, border, bordercolor, backgroud;
        recv_data >> backgroud >> icon >> iconcolor >> border >> bordercolor;

        at->SetEmblem(backgroud, icon, iconcolor, border, bordercolor);

        // register team and add captain
        sObjectMgr.AddArenaTeam(at);
        sLog.outDebug("PetitonsHandler: arena team added to objmrg");

        // add members
        for (uint8 i = 0; i < signs; ++i)
        {
            Field* fields = result->Fetch();
            uint64 memberGUID = fields[0].GetUInt64();
            sLog.outDebug("PetitionsHandler: adding arena member %u", GUID_LOPART(memberGUID));
            at->AddMember(memberGUID);
            result->NextRow();
        }
    }

    RealmDataDatabase.BeginTransaction();
    RealmDataDatabase.PExecute("DELETE FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid));
    RealmDataDatabase.PExecute("DELETE FROM petition_sign WHERE petitionguid = '%u'", GUID_LOPART(petitionguid));
    RealmDataDatabase.CommitTransaction();

    // created
    sLog.outDebug("TURN IN PETITION GUID %u", GUID_LOPART(petitionguid));

    data.Initialize(SMSG_TURN_IN_PETITION_RESULTS, 4);
    data << (uint32)PETITION_TURN_OK;
    SendPacket(&data);
}
Exemple #22
0
void WorldSession::HandleOfferPetitionOpcode(WorldPacket & recv_data)
{
    CHECK_PACKET_SIZE(recv_data, 4+8+8);

    sLog.outDebug("Received opcode CMSG_OFFER_PETITION");   // ok
    //recv_data.hexlike();

    uint8 signs = 0;
    uint64 petitionguid, plguid;
    uint32 type, junk;
    Player *player;
    recv_data >> junk;                                      // this is not petition type!
    recv_data >> petitionguid;                              // petition guid
    recv_data >> plguid;                                    // player guid

    player = ObjectAccessor::FindPlayer(plguid);
    if (!player)
        return;

    QueryResultAutoPtr result = RealmDataDatabase.PQuery("SELECT type FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid));
    if (!result)
        return;

    Field *fields = result->Fetch();
    type = fields[0].GetUInt32();

    sLog.outDebug("OFFER PETITION: type %u, GUID1 %u, to player id: %u", type, GUID_LOPART(petitionguid), GUID_LOPART(plguid));

    if (!sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && GetPlayer()->GetTeam() != player->GetTeam())
    {
        if (type != 9)
            SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", "", ERR_ARENA_TEAM_NOT_ALLIED);
        else
            SendGuildCommandResult(GUILD_CREATE_S, "", GUILD_NOT_ALLIED);
        return;
    }

    if (type != 9)
    {
        if (player->getLevel() < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL))
        {
            // player is too low level to join an arena team
            SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, player->GetName(), "", ERR_ARENA_TEAM_PLAYER_TO_LOW);
            return;
        }

        uint8 slot = ArenaTeam::GetSlotByType(type);
        if (slot >= MAX_ARENA_SLOT)
            return;

        if (player->GetArenaTeamId(slot))
        {
            // player is already in an arena team
            SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, player->GetName(), "", ERR_ALREADY_IN_ARENA_TEAM_S);
            return;
        }

        if (player->GetArenaTeamIdInvited())
        {
            SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", _player->GetName(), ERR_ALREADY_INVITED_TO_ARENA_TEAM_S);
            return;
        }
    }
    else
    {
        if (player->GetGuildId())
        {
            SendGuildCommandResult(GUILD_INVITE_S, _player->GetName(), ALREADY_IN_GUILD);
            return;
        }

        if (player->GetGuildIdInvited())
        {
            SendGuildCommandResult(GUILD_INVITE_S, _player->GetName(), ALREADY_INVITED_TO_GUILD);
            return;
        }
    }

    result = RealmDataDatabase.PQuery("SELECT playerguid FROM petition_sign WHERE petitionguid = '%u'", GUID_LOPART(petitionguid));
    // result==NULL also correct charter without signs
    if (result)
        signs = result->GetRowCount();

    WorldPacket data(SMSG_PETITION_SHOW_SIGNATURES, (8+8+4+signs+signs*12));
    data << petitionguid;                                   // petition guid
    data << _player->GetGUID();                             // owner guid
    data << GUID_LOPART(petitionguid);                      // guild guid (in Trinity always same as GUID_LOPART(petition guid)
    data << signs;                                          // sign's count

    for (uint8 i = 1; i <= signs; i++)
    {
        Field *fields2 = result->Fetch();
        uint64 plguid = fields2[0].GetUInt64();

        data << plguid;                                     // Player GUID
        data << (uint32)0;                                  // there 0 ...

        result->NextRow();
    }

    player->SendPacketToSelf(&data);
}
Exemple #23
0
void WorldSession::HandlePetitionBuyOpcode(WorldPacket & recv_data)
{
    CHECK_PACKET_SIZE(recv_data, 8+8+4+1+5*8+2+1+4+4);

    sLog.outDebug("Received opcode CMSG_PETITION_BUY");
    //recv_data.hexlike();

    uint64 guidNPC;
    uint64 unk1, unk3, unk4, unk5, unk6, unk7;
    uint32 unk2;
    std::string name;
    uint16 unk8;
    uint8  unk9;
    uint32 unk10;                                           // selected index
    uint32 unk11;
    recv_data >> guidNPC;                                   // NPC GUID
    recv_data >> unk1;                                      // 0
    recv_data >> unk2;                                      // 0
    recv_data >> name;                                      // name

    // recheck
    CHECK_PACKET_SIZE(recv_data, 8+8+4+(name.size()+1)+5*8+2+1+4+4);

    recv_data >> unk3;                                      // 0
    recv_data >> unk4;                                      // 0
    recv_data >> unk5;                                      // 0
    recv_data >> unk6;                                      // 0
    recv_data >> unk7;                                      // 0
    recv_data >> unk8;                                      // 0
    recv_data >> unk9;                                      // 0
    recv_data >> unk10;                                     // index
    recv_data >> unk11;                                     // 0
    sLog.outDebug("Petitioner with GUID %u tried sell petition: name %s", GUID_LOPART(guidNPC), name.c_str());

    // prevent cheating
    Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(guidNPC, UNIT_NPC_FLAG_PETITIONER);
    if (!pCreature)
    {
        sLog.outDebug("WORLD: HandlePetitionBuyOpcode - Unit (GUID: %u) not found or you can't interact with him.", GUID_LOPART(guidNPC));
        return;
    }

    // remove fake death
    if (GetPlayer()->hasUnitState(UNIT_STAT_DIED))
        GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);

    uint32 charterid = 0;
    uint32 cost = 0;
    uint32 type = 0;
    if (pCreature->isTabardDesigner())
    {
        // if tabard designer, then trying to buy a guild charter.
        // do not let if already in guild.
        if (_player->GetGuildId())
            return;

        charterid = GUILD_CHARTER;
        cost = GUILD_CHARTER_COST;
        type = 9;
    }
    else
    {
        // TODO: find correct opcode
        if (_player->getLevel() < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL))
        {
            SendNotification(LANG_ARENA_ONE_TOOLOW, sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL));
            return;
        }

        switch (unk10)
        {
            case 1:
                charterid = ARENA_TEAM_CHARTER_2v2;
                cost = ARENA_TEAM_CHARTER_2v2_COST;
                type = 2;                                   // 2v2
                break;
            case 2:
                charterid = ARENA_TEAM_CHARTER_3v3;
                cost = ARENA_TEAM_CHARTER_3v3_COST;
                type = 3;                                   // 3v3
                break;
            case 3:
                charterid = ARENA_TEAM_CHARTER_5v5;
                cost = ARENA_TEAM_CHARTER_5v5_COST;
                type = 5;                                   // 5v5
                break;
            default:
                sLog.outDebug("unknown selection at buy petition: %u", unk10);
                return;
        }

        if (_player->GetArenaTeamId(unk10-1))
        {
            SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ALREADY_IN_ARENA_TEAM);
            return;
        }
    }

    if (type == 9)
    {
        if (sGuildMgr.GetGuildByName(name))
        {
            SendGuildCommandResult(GUILD_CREATE_S, name, GUILD_NAME_EXISTS);
            return;
        }
        if (sObjectMgr.IsReservedName(name) || !ObjectMgr::IsValidCharterName(name))
        {
            SendGuildCommandResult(GUILD_CREATE_S, name, GUILD_NAME_INVALID);
            return;
        }
    }
    else
    {
        if (sObjectMgr.GetArenaTeamByName(name))
        {
            SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ARENA_TEAM_NAME_EXISTS_S);
            return;
        }
        if (sObjectMgr.IsReservedName(name) || !ObjectMgr::IsValidCharterName(name))
        {
            SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ARENA_TEAM_NAME_INVALID);
            return;
        }
    }

    ItemPrototype const *pProto = ObjectMgr::GetItemPrototype(charterid);
    if (!pProto)
    {
        _player->SendBuyError(BUY_ERR_CANT_FIND_ITEM, NULL, charterid, 0);
        return;
    }

    if (_player->GetMoney() < cost)
    {                                                       //player hasn't got enough money
        _player->SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, pCreature, charterid, 0);
        return;
    }

    ItemPosCountVec dest;
    uint8 msg = _player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, charterid, pProto->BuyCount);
    if (msg != EQUIP_ERR_OK)
    {
        _player->SendBuyError(msg, pCreature, charterid, 0);
        return;
    }

    _player->ModifyMoney(-(int32)cost);
    Item *charter = _player->StoreNewItem(dest, charterid, true);
    if (!charter)
        return;

    charter->SetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1, charter->GetGUIDLow());
    // ITEM_FIELD_ENCHANTMENT_1_1 is guild/arenateam id
    // ITEM_FIELD_ENCHANTMENT_1_1+1 is current signatures count (showed on item)
    charter->SetState(ITEM_CHANGED, _player);
    _player->SendNewItem(charter, 1, true, false);

    // a petition is invalid, if both the owner and the type matches
    // we checked above, if this player is in an arenateam, so this must be
    // datacorruption
    QueryResultAutoPtr result = RealmDataDatabase.PQuery("SELECT petitionguid FROM petition WHERE ownerguid = '%u'  AND type = '%u'", _player->GetGUIDLow(), type);

    std::ostringstream ssInvalidPetitionGUIDs;

    if (result)
    {

        do
        {
            Field *fields = result->Fetch();
            ssInvalidPetitionGUIDs << "'" << fields[0].GetUInt32() << "' , ";
        }
        while (result->NextRow());
    }

    // delete petitions with the same guid as this one
    ssInvalidPetitionGUIDs << "'" << charter->GetGUIDLow() << "'";

    sLog.outDebug("Invalid petition GUIDs: %s", ssInvalidPetitionGUIDs.str().c_str());
    RealmDataDatabase.escape_string(name);
    RealmDataDatabase.BeginTransaction();
    RealmDataDatabase.PExecute("DELETE FROM petition WHERE petitionguid IN (%s)",  ssInvalidPetitionGUIDs.str().c_str());
    RealmDataDatabase.PExecute("DELETE FROM petition_sign WHERE petitionguid IN (%s)", ssInvalidPetitionGUIDs.str().c_str());
    RealmDataDatabase.PExecute("INSERT INTO petition (ownerguid, petitionguid, name, type) VALUES ('%u', '%u', '%s', '%u')",
        _player->GetGUIDLow(), charter->GetGUIDLow(), name.c_str(), type);
    RealmDataDatabase.CommitTransaction();
}
Exemple #24
0
void WorldSession::HandlePetitionSignOpcode(WorldPacket & recv_data)
{
    CHECK_PACKET_SIZE(recv_data, 8+1);

    sLog.outDebug("Received opcode CMSG_PETITION_SIGN");    // ok
    //recv_data.hexlike();

    Field *fields;
    uint64 petitionguid;
    uint8 unk;
    recv_data >> petitionguid;                              // petition guid
    recv_data >> unk;

    QueryResultAutoPtr result = RealmDataDatabase.PQuery(
        "SELECT ownerguid, "
        "  (SELECT COUNT(playerguid) FROM petition_sign WHERE petition_sign.petitionguid = '%u') AS signs, "
        "  type "
        "FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid), GUID_LOPART(petitionguid));

    if (!result)
    {
        sLog.outLog(LOG_DEFAULT, "ERROR: any petition on server...");
        return;
    }

    fields = result->Fetch();
    uint64 ownerguid = MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER);
    uint8 signs = fields[1].GetUInt8();
    uint32 type = fields[2].GetUInt32();

    uint32 plguidlo = _player->GetGUIDLow();
    if (GUID_LOPART(ownerguid) == plguidlo)
        return;

    // not let enemies sign guild charter
    if (!sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && GetPlayer()->GetTeam() != sObjectMgr.GetPlayerTeamByGUID(ownerguid))
    {
        if (type != 9)
            SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", "", ERR_ARENA_TEAM_NOT_ALLIED);
        else
            SendGuildCommandResult(GUILD_CREATE_S, "", GUILD_NOT_ALLIED);
        return;
    }

    if (type != 9)
    {
        if (_player->getLevel() < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL))
        {
            SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", _player->GetName(), ERR_ARENA_TEAM_PLAYER_TO_LOW);
            return;
        }

        uint8 slot = ArenaTeam::GetSlotByType(type);
        if (slot >= MAX_ARENA_SLOT)
            return;

        if (_player->GetArenaTeamId(slot))
        {
            SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", _player->GetName(), ERR_ALREADY_IN_ARENA_TEAM_S);
            return;
        }

        if (_player->GetArenaTeamIdInvited())
        {
            SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", _player->GetName(), ERR_ALREADY_INVITED_TO_ARENA_TEAM_S);
            return;
        }
    }
    else
    {
        if (_player->GetGuildId())
        {
            SendGuildCommandResult(GUILD_INVITE_S, _player->GetName(), ALREADY_IN_GUILD);
            return;
        }
        if (_player->GetGuildIdInvited())
        {
            SendGuildCommandResult(GUILD_INVITE_S, _player->GetName(), ALREADY_INVITED_TO_GUILD);
            return;
        }
    }

    if (++signs > type)                                        // client signs maximum
        return;

    //client doesn't allow to sign petition two times by one character, but not check sign by another character from same account
    //not allow sign another player from already sign player account
    result = RealmDataDatabase.PQuery("SELECT playerguid FROM petition_sign WHERE player_account = '%u' AND petitionguid = '%u'", GetAccountId(), GUID_LOPART(petitionguid));

    if (result)
    {
        WorldPacket data(SMSG_PETITION_SIGN_RESULTS, (8+8+4));
        data << petitionguid;
        data << _player->GetGUID();
        data << (uint32)PETITION_SIGN_ALREADY_SIGNED;

        // close at signer side
        SendPacket(&data);

        // update for owner if online
        if (Player *owner = sObjectMgr.GetPlayer(ownerguid))
            owner->SendPacketToSelf(&data);
        return;
    }

    RealmDataDatabase.PExecute("INSERT INTO petition_sign (ownerguid,petitionguid, playerguid, player_account) VALUES ('%u', '%u', '%u','%u')", GUID_LOPART(ownerguid),GUID_LOPART(petitionguid), plguidlo,GetAccountId());

    sLog.outDebug("PETITION SIGN: GUID %u by player: %s (GUID: %u Account: %u)", GUID_LOPART(petitionguid), _player->GetName(),plguidlo,GetAccountId());

    WorldPacket data(SMSG_PETITION_SIGN_RESULTS, (8+8+4));
    data << petitionguid;
    data << _player->GetGUID();
    data << (uint32)PETITION_SIGN_OK;

    // close at signer side
    SendPacket(&data);

    // update signs count on charter, required testing...
    //Item *item = _player->GetItemByGuid(petitionguid));
    //if(item)
    //    item->SetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1+1, signs);

    // update for owner if online
    if (Player *owner = sObjectMgr.GetPlayer(ownerguid))
        owner->SendPacketToSelf(&data);
}
Exemple #25
0
void WorldSession::HandlePetitionRenameOpcode(WorldPacket & recv_data)
{
    CHECK_PACKET_SIZE(recv_data, 8+1);

    sLog.outDebug("Received opcode MSG_PETITION_RENAME");   // ok
    //recv_data.hexlike();

    uint64 petitionguid;
    uint32 type;
    std::string newname;

    recv_data >> petitionguid;                              // guid
    recv_data >> newname;                                   // new name

    Item *item = _player->GetItemByGuid(petitionguid);
    if (!item)
        return;

    QueryResultAutoPtr result = RealmDataDatabase.PQuery("SELECT type FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid));

    if (result)
    {
        Field* fields = result->Fetch();
        type = fields[0].GetUInt32();
    }
    else
    {
        sLog.outDebug("CMSG_PETITION_QUERY failed for petition (GUID: %u)", GUID_LOPART(petitionguid));
        return;
    }

    if (type == 9)
    {
        if (sGuildMgr.GetGuildByName(newname))
        {
            SendGuildCommandResult(GUILD_CREATE_S, newname, GUILD_NAME_EXISTS);
            return;
        }
        if (sObjectMgr.IsReservedName(newname) || !ObjectMgr::IsValidCharterName(newname))
        {
            SendGuildCommandResult(GUILD_CREATE_S, newname, GUILD_NAME_INVALID);
            return;
        }
    }
    else
    {
        if (sObjectMgr.GetArenaTeamByName(newname))
        {
            SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, newname, "", ERR_ARENA_TEAM_NAME_EXISTS_S);
            return;
        }
        if (sObjectMgr.IsReservedName(newname) || !ObjectMgr::IsValidCharterName(newname))
        {
            SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, newname, "", ERR_ARENA_TEAM_NAME_INVALID);
            return;
        }
    }

    std::string db_newname = newname;
    RealmDataDatabase.escape_string(db_newname);
    RealmDataDatabase.PExecute("UPDATE petition SET name = '%s' WHERE petitionguid = '%u'",
        db_newname.c_str(), GUID_LOPART(petitionguid));

    sLog.outDebug("Petition (GUID: %u) renamed to '%s'", GUID_LOPART(petitionguid), newname.c_str());
    WorldPacket data(MSG_PETITION_RENAME, (8+newname.size()+1));
    data << petitionguid;
    data << newname;
    SendPacket(&data);
}
/// Logon Challenge command handler
bool AuthSocket::_HandleLogonChallenge()
{
    DEBUG_LOG("Entering _HandleLogonChallenge");
    if (recv_len() < sizeof(sAuthLogonChallenge_C))
        return false;

    ///- Read the first 4 bytes (header) to get the length of the remaining of the packet
    std::vector<uint8> buf;
    buf.resize(4);

    recv((char *)&buf[0], 4);

    EndianConvert(*((uint16*)(buf[0])));
    uint16 remaining = ((sAuthLogonChallenge_C *)&buf[0])->size;
    DEBUG_LOG("[AuthChallenge] got header, body is %#04x bytes", remaining);

    if ((remaining < sizeof(sAuthLogonChallenge_C) - buf.size()) || (recv_len() < remaining))
        return false;

    //No big fear of memory outage (size is int16, i.e. < 65536)
    buf.resize(remaining + buf.size() + 1);
    buf[buf.size() - 1] = 0;
    sAuthLogonChallenge_C *ch = (sAuthLogonChallenge_C*)&buf[0];

    ///- Read the remaining of the packet
    recv((char *)&buf[4], remaining);
    DEBUG_LOG("[AuthChallenge] got full packet, %#04x bytes", ch->size);
    DEBUG_LOG("[AuthChallenge] name(%d): '%s'", ch->I_len, ch->I);

    // BigEndian code, nop in little endian case
    // size already converted
    EndianConvert(*((uint32*)(&ch->gamename[0])));
    EndianConvert(ch->build);
    EndianConvert(*((uint32*)(&ch->platform[0])));
    EndianConvert(*((uint32*)(&ch->os[0])));
    EndianConvert(*((uint32*)(&ch->country[0])));
    EndianConvert(ch->timezone_bias);
    EndianConvert(*((uint32*)(&ch->ip[0])));

    std::stringstream tmpLocalIp;
    tmpLocalIp << (uint32)ch->ip[0] << "." << (uint32)ch->ip[1] << "." << (uint32)ch->ip[2] << "." << (uint32)ch->ip[3];

    localIp_ = tmpLocalIp.str();

    ByteBuffer pkt;

    _login = (const char*)ch->I;
    _build = ch->build;
    operatingSystem_ = (const char*)ch->os;

    // Restore string order as its byte order is reversed
    std::reverse(operatingSystem_.begin(), operatingSystem_.end());

    if (operatingSystem_.size() > 4 || (operatingSystem_ != "Win" && operatingSystem_ != "OSX" && (sRealmList.ChatboxOsName == "" || operatingSystem_ != sRealmList.ChatboxOsName))){
        sLog.outLog(LOG_WARDEN, "Client %s got unsupported operating system (%s)", _login.c_str(), operatingSystem_.c_str());
        return false;
    }

    ///- Normalize account name
    //utf8ToUpperOnlyLatin(_login); -- client already send account in expected form

    //Escape the user login to avoid further SQL injection
    //Memory will be freed on AuthSocket object destruction
    _safelogin = _login;
    AccountsDatabase.escape_string(_safelogin);

    pkt << (uint8) CMD_AUTH_LOGON_CHALLENGE;
    pkt << (uint8) 0x00;

    std::string address = get_remote_address();

#ifdef REGEX_NAMESPACE
    for (PatternList::const_iterator i = pattern_banned.begin(); i != pattern_banned.end(); ++i)
    {
        if (REGEX_NAMESPACE::regex_match(address.c_str(), i->first) && REGEX_NAMESPACE::regex_match(localIp_.c_str(), i->second))
        {
            pkt<< (uint8) WOW_FAIL_UNKNOWN_ACCOUNT;
            send((char const*)pkt.contents(), pkt.size());
            return true;
        }
    }
#endif

    ///- Verify that this IP is not in the ip_banned table
    // No SQL injection possible (paste the IP address as passed by the socket)
    AccountsDatabase.Execute("DELETE FROM ip_banned WHERE unbandate<=UNIX_TIMESTAMP() AND unbandate<>bandate");
    AccountsDatabase.escape_string(address);
    //Delete ViP
	AccountsDatabase.Execute("UPDATE account_permissions SET permission_mask = 1 WHERE unsetdate<=UNIX_TIMESTAMP() AND unsetdate<>setdate");
    QueryResultAutoPtr result = AccountsDatabase.PQuery("SELECT * FROM ip_banned WHERE ip = '%s'", address.c_str());

    if (result) // ip banned
    {
        sLog.outBasic("[AuthChallenge] Banned ip %s tries to login!", get_remote_address().c_str());
        pkt << uint8(WOW_FAIL_BANNED);
        send((char const*)pkt.contents(), pkt.size());
        return true;
    }

    ///- Get the account details from the account table
    // No SQL injection (escaped user name)

    result = AccountsDatabase.PQuery("SELECT pass_hash, account.account_id, account_state_id, last_ip, permission_mask, email "
                                     "FROM account JOIN account_permissions ON account.account_id = account_permissions.account_id "
                                     "WHERE username = '******'", _safelogin.c_str());

    if (!result)    // account not exists
    {
        pkt<< uint8(WOW_FAIL_UNKNOWN_ACCOUNT);
        send((char const*)pkt.contents(), pkt.size());
        return true;
    }

    Field * fields = result->Fetch();

    ///- If the IP is 'locked', check that the player comes indeed from the correct IP address
    switch (fields[2].GetUInt8())
    {
        case ACCOUNT_STATE_IP_LOCKED:
        {
            DEBUG_LOG("[AuthChallenge] Account '%s' is locked to IP - '%s'", _login.c_str(), (*result)[3].GetString());
            DEBUG_LOG("[AuthChallenge] Player address is '%s'", get_remote_address().c_str());
            if (strcmp(fields[4].GetString(), get_remote_address().c_str()))
            {
                DEBUG_LOG("[AuthChallenge] Account IP differs");
                    pkt << (uint8) WOW_FAIL_LOCKED_ENFORCED;
                send((char const*)pkt.contents(), pkt.size());
                return true;
            }
            else
            {
                DEBUG_LOG("[AuthChallenge] Account IP matches");
            }
            break;
        }
        case ACCOUNT_STATE_FROZEN:
        {
            pkt << uint8(WOW_FAIL_SUSPENDED);
            send((char const*)pkt.contents(), pkt.size());
            return true;
        }
        default:
            DEBUG_LOG("[AuthChallenge] Account '%s' is not locked to ip or frozen", _login.c_str());
            break;
    }

    ///- If the account is banned, reject the logon attempt
    QueryResultAutoPtr  banresult = AccountsDatabase.PQuery("SELECT punishment_date, expiration_date "
                                                            "FROM account_punishment "
                                                            "WHERE account_id = '%u' AND punishment_type_id = '%u' AND (punishment_date = expiration_date OR expiration_date > UNIX_TIMESTAMP())", (*result)[1].GetUInt32(), PUNISHMENT_BAN);

    if (banresult)
    {
        if((*banresult)[0].GetUInt64() == (*banresult)[1].GetUInt64())
        {
            pkt << uint8(WOW_FAIL_BANNED);
            sLog.outBasic("[AuthChallenge] Banned account %s tries to login!", _login.c_str ());
        }
        else
        {
            pkt << uint8(WOW_FAIL_SUSPENDED);
            sLog.outBasic("[AuthChallenge] Temporarily banned account %s tries to login!", _login.c_str ());
        }

        send((char const*)pkt.contents(), pkt.size());
        return true;
    }

    QueryResultAutoPtr  emailbanresult = AccountsDatabase.PQuery("SELECT email FROM email_banned WHERE email = '%s'", (*result)[5].GetString());
    if (emailbanresult)
    {
        pkt << uint8(WOW_FAIL_BANNED);
        sLog.outBasic("[AuthChallenge] Account %s with banned email %s tries to login!", _login.c_str (), (*emailbanresult)[0].GetString());

        send((char const*)pkt.contents(), pkt.size());
        return true;
    }

    ///- Get the password from the account table, upper it, and make the SRP6 calculation
    std::string rI = fields[0].GetCppString();

    _SetVSFields(rI);

    b.SetRand(19 * 8);
    BigNumber gmod = g.ModExp(b, N);
    B = ((v * 3) + gmod) % N;

    ASSERT(gmod.GetNumBytes() <= 32);

    BigNumber unk3;
    unk3.SetRand(16 * 8);

    ///- Fill the response packet with the result
    pkt << uint8(WOW_SUCCESS);

    // B may be calculated < 32B so we force minimal length to 32B
    pkt.append(B.AsByteArray(32), 32);      // 32 bytes
    pkt << uint8(1);
    pkt.append(g.AsByteArray(), 1);
    pkt << uint8(32);
    pkt.append(N.AsByteArray(32), 32);
    pkt.append(s.AsByteArray(), s.GetNumBytes());// 32 bytes
    pkt.append(unk3.AsByteArray(16), 16);
    uint8 securityFlags = 0;
    pkt << uint8(securityFlags);            // security flags (0x0...0x04)

    if (securityFlags & 0x01)                // PIN input
    {
        pkt << uint32(0);
        pkt << uint64(0) << uint64(0);      // 16 bytes hash?
    }

    if (securityFlags & 0x02)                // Matrix input
    {
        pkt << uint8(0);
        pkt << uint8(0);
        pkt << uint8(0);
        pkt << uint8(0);
        pkt << uint64(0);
    }

    if (securityFlags & 0x04)                // Security token input
        pkt << uint8(1);

    accountPermissionMask_ = fields[4].GetUInt64();

    _localizationName.resize(4);
    for (int i = 0; i < 4; ++i)
        _localizationName[i] = ch->country[4-i-1];

    sLog.outBasic("[AuthChallenge] account %s is using '%c%c%c%c' locale (%u)", _login.c_str (), ch->country[3], ch->country[2], ch->country[1], ch->country[0], GetLocaleByName(_localizationName));

    send((char const*)pkt.contents(), pkt.size());
    return true;
}
/// Logon Proof command handler
bool AuthSocket::_HandleLogonProof()
{
    DEBUG_LOG("Entering _HandleLogonProof");
    ///- Read the packet
    sAuthLogonProof_C lp;
    if(!recv((char *)&lp, sizeof(sAuthLogonProof_C)))
        return false;

    ///- Check if the client has one of the expected version numbers
    bool valid_version = FindBuildInfo(_build) != NULL;

    /// <ul><li> If the client has no valid version
    if(!valid_version)
    {
        if (this->patch_ != ACE_INVALID_HANDLE)
            return false;

        ///- Check if we have the apropriate patch on the disk
        // file looks like: 65535enGB.mpq
        char tmp[64];

        snprintf(tmp, 24, "./patches/%d%s.mpq", _build, _localizationName.c_str());

        char filename[PATH_MAX];
        if (ACE_OS::realpath(tmp, filename) != NULL)
        {
            patch_ = ACE_OS::open(filename, GENERIC_READ | FILE_FLAG_SEQUENTIAL_SCAN);
        }

        if (patch_ == ACE_INVALID_HANDLE)
        {
            // no patch found
            ByteBuffer pkt;
            pkt << (uint8) CMD_AUTH_LOGON_CHALLENGE;
            pkt << (uint8) 0x00;
            pkt << (uint8) WOW_FAIL_VERSION_INVALID;
            DEBUG_LOG("[AuthChallenge] %u is not a valid client version!", _build);
            DEBUG_LOG("[AuthChallenge] Patch %s not found", tmp);
            send((char const*)pkt.contents(), pkt.size());
            return true;
        }

        XFER_INIT xferh;

        ACE_OFF_T file_size = ACE_OS::filesize(this->patch_);

        if (file_size == -1)
        {
            close_connection();
            return false;
        }

        if (!PatchCache::instance()->GetHash(tmp, (uint8*)&xferh.md5))
        {
            // calculate patch md5, happens if patch was added while realmd was running
            PatchCache::instance()->LoadPatchMD5(tmp);
            PatchCache::instance()->GetHash(tmp, (uint8*)&xferh.md5);
        }

        uint8 data[2] = { CMD_AUTH_LOGON_PROOF, WOW_FAIL_VERSION_UPDATE};
        send((const char*)data, sizeof(data));

        memcpy(&xferh, "0\x05Patch", 7);
        xferh.cmd = CMD_XFER_INITIATE;
        xferh.file_size = file_size;

        send((const char*)&xferh, sizeof(xferh));
        return true;
    }
    /// </ul>

    ///- Continue the SRP6 calculation based on data received from the client
    BigNumber A;

    A.SetBinary(lp.A, 32);

    // SRP safeguard: abort if A==0
    if (A.isZero())
        return false;

    Sha1Hash sha;
    sha.UpdateBigNumbers(&A, &B, NULL);
    sha.Finalize();
    BigNumber u;
    u.SetBinary(sha.GetDigest(), 20);
    BigNumber S = (A * (v.ModExp(u, N))).ModExp(b, N);

    uint8 t[32];
    uint8 t1[16];
    uint8 vK[40];
    memcpy(t, S.AsByteArray(32), 32);
    for (int i = 0; i < 16; ++i)
    {
        t1[i] = t[i * 2];
    }
    sha.Initialize();
    sha.UpdateData(t1, 16);
    sha.Finalize();
    for (int i = 0; i < 20; ++i)
    {
        vK[i * 2] = sha.GetDigest()[i];
    }
    for (int i = 0; i < 16; ++i)
    {
        t1[i] = t[i * 2 + 1];
    }
    sha.Initialize();
    sha.UpdateData(t1, 16);
    sha.Finalize();
    for (int i = 0; i < 20; ++i)
    {
        vK[i * 2 + 1] = sha.GetDigest()[i];
    }
    K.SetBinary(vK, 40);

    uint8 hash[20];

    sha.Initialize();
    sha.UpdateBigNumbers(&N, NULL);
    sha.Finalize();
    memcpy(hash, sha.GetDigest(), 20);
    sha.Initialize();
    sha.UpdateBigNumbers(&g, NULL);
    sha.Finalize();
    for (int i = 0; i < 20; ++i)
    {
        hash[i] ^= sha.GetDigest()[i];
    }
    BigNumber t3;
    t3.SetBinary(hash, 20);

    sha.Initialize();
    sha.UpdateData(_login);
    sha.Finalize();
    uint8 t4[SHA_DIGEST_LENGTH];
    memcpy(t4, sha.GetDigest(), SHA_DIGEST_LENGTH);

    sha.Initialize();
    sha.UpdateBigNumbers(&t3, NULL);
    sha.UpdateData(t4, SHA_DIGEST_LENGTH);
    sha.UpdateBigNumbers(&s, &A, &B, &K, NULL);
    sha.Finalize();
    BigNumber M;
    M.SetBinary(sha.GetDigest(), 20);

    ///- Check if SRP6 results match (password is correct), else send an error
    if (!memcmp(M.AsByteArray(), lp.M1, 20))
    {
        sLog.outBasic("User '%s' successfully authenticated", _login.c_str());

        uint8 OS;

        if (!strcmp(operatingSystem_.c_str(), "Win"))
            OS = CLIENT_OS_WIN;
        else if (!strcmp(operatingSystem_.c_str(), "OSX"))
            OS = CLIENT_OS_OSX;
        else if (!strcmp(operatingSystem_.c_str(), "CHA") ||
                 !strcmp(operatingSystem_.c_str(), "CHAT"))
            OS = CLIENT_OS_CHAT;
        else
        {
            OS = CLIENT_OS_UNKNOWN;
            AccountsDatabase.escape_string(operatingSystem_);
            sLog.outLog(LOG_WARDEN, "Client %s got unsupported operating system (%s)", _safelogin.c_str(), operatingSystem_.c_str());
        }

        ///- Update the sessionkey, last_ip, last login time and reset number of failed logins in the account table for this account
        // No SQL injection (escaped user name) and IP address as received by socket
        const char* K_hex = K.AsHexStr();

        QueryResultAutoPtr result = AccountsDatabase.PQuery("SELECT account_id FROM account WHERE username = '******'", _safelogin.c_str());

        if (!result)
        {
            if (_build > 6005)                                  // > 1.12.2
            {
                char data[4] = { CMD_AUTH_LOGON_PROOF, WOW_FAIL_UNKNOWN_ACCOUNT, 3, 0};
                send(data, sizeof(data));
            }
            else
            {
                // 1.x not react incorrectly at 4-byte message use 3 as real error
                char data[2] = { CMD_AUTH_LOGON_PROOF, WOW_FAIL_UNKNOWN_ACCOUNT};
                send(data, sizeof(data));
            }
            return true;
        }

        uint32 accId = result->Fetch()->GetUInt32();

        // direct to be sure that values will be set before character choose, this will slow down logging in a bit ;p
        AccountsDatabase.DirectPExecute("UPDATE account_session SET session_key = '%s' WHERE account_id = '%u'", K_hex, accId);

        static SqlStatementID updateAccount;
        SqlStatement stmt = AccountsDatabase.CreateStatement(updateAccount, "UPDATE account SET last_ip = ?, last_local_ip = ?, last_login = NOW(), locale_id = ?, failed_logins = 0, client_os_version_id = ? WHERE account_id = ?");
        std::string tmpIp = get_remote_address();
        stmt.addString(tmpIp.c_str());
        stmt.addString(localIp_.c_str());
        stmt.addUInt8(uint8(GetLocaleByName(_localizationName)));
        stmt.addUInt8(OS);
        stmt.addUInt32(accId);
        stmt.DirectExecute();

        OPENSSL_free((void*)K_hex);

        ///- Finish SRP6 and send the final result to the client
        sha.Initialize();
        sha.UpdateBigNumbers(&A, &M, &K, NULL);
        sha.Finalize();

        SendProof(sha);

        ///- Set _authed to true!
        _authed = true;
    }
    else
    {
        if (_build > 6005)                                  // > 1.12.2
        {
            char data[4] = { CMD_AUTH_LOGON_PROOF, WOW_FAIL_UNKNOWN_ACCOUNT, 3, 0};
            send(data, sizeof(data));
        }
        else
        {
            // 1.x not react incorrectly at 4-byte message use 3 as real error
            char data[2] = { CMD_AUTH_LOGON_PROOF, WOW_FAIL_UNKNOWN_ACCOUNT};
            send(data, sizeof(data));
        }
        sLog.outBasic("[AuthChallenge] account %s tried to login with wrong password!",_login.c_str ());

        uint32 MaxWrongPassCount = sConfig.GetIntDefault("WrongPass.MaxCount", 0);
        if (MaxWrongPassCount > 0)
        {
            static SqlStatementID updateAccountFailedLogins;
            //Increment number of failed logins by one and if it reaches the limit temporarily ban that account or IP
            SqlStatement stmt = AccountsDatabase.CreateStatement(updateAccountFailedLogins, "UPDATE account SET failed_logins = failed_logins + 1 WHERE username = ?");
            stmt.addString(_login);
            stmt.Execute();

            if (QueryResultAutoPtr loginfail = AccountsDatabase.PQuery("SELECT account_id, failed_logins FROM account WHERE username = '******'", _safelogin.c_str()))
            {
                Field* fields = loginfail->Fetch();
                uint32 failed_logins = fields[1].GetUInt32();

                if (failed_logins >= MaxWrongPassCount)
                {
                    uint32 WrongPassBanTime = sConfig.GetIntDefault("WrongPass.BanTime", 600);
                    bool WrongPassBanType = sConfig.GetBoolDefault("WrongPass.BanType", false);

                    if (WrongPassBanType)
                    {
                        uint32 acc_id = fields[0].GetUInt32();
                        AccountsDatabase.PExecute("INSERT INTO account_punishment VALUES ('%u', '%u', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()+%u, 'Realm', 'Incorrect password for: %u times. Ban for: %u seconds')",
                                                acc_id, PUNISHMENT_BAN, WrongPassBanTime, failed_logins, WrongPassBanTime);
                        sLog.outBasic("[AuthChallenge] account %s got banned for '%u' seconds because it failed to authenticate '%u' times",
                            _login.c_str(), WrongPassBanTime, failed_logins);
                    }
                    else
                    {
                        std::string current_ip = get_remote_address();
                        AccountsDatabase.escape_string(current_ip);
                        AccountsDatabase.PExecute("INSERT INTO ip_banned VALUES ('%s',UNIX_TIMESTAMP(),UNIX_TIMESTAMP()+'%u','Realm','Incorrect password for: %u times. Ban for: %u seconds')",
                            current_ip.c_str(), WrongPassBanTime, failed_logins, WrongPassBanTime);
                        sLog.outBasic("[AuthChallenge] IP %s got banned for '%u' seconds because account %s failed to authenticate '%u' times",
                            current_ip.c_str(), WrongPassBanTime, _login.c_str(), failed_logins);
                    }
                }
            }
        }
    }
    return true;
}
void AuthSocket::LoadRealmlist(ByteBuffer &pkt, uint32 acctid)
{
    switch (_build)
    {
        case 5875:                                          // 1.12.1
        case 6005:                                          // 1.12.2
        {
            pkt << uint32(0);                               // unused value
            pkt << uint8(sRealmList.size());

            for (RealmList::RealmMap::const_iterator  i = sRealmList.begin(); i != sRealmList.end(); ++i)
            {
                uint8 AmountOfCharacters;

                // No SQL injection. id of realm is controlled by the database.
                QueryResultAutoPtr result = AccountsDatabase.PQuery( "SELECT characters_count FROM realm_characters WHERE realm_id = '%u' AND account_id = '%u'", i->second.m_ID, acctid);
                if (result)
                {
                    Field *fields = result->Fetch();
                    AmountOfCharacters = fields[0].GetUInt8();
                }
                else
                    AmountOfCharacters = 0;

                bool ok_build = std::find(i->second.realmbuilds.begin(), i->second.realmbuilds.end(), _build) != i->second.realmbuilds.end();

                RealmBuildInfo const* buildInfo = ok_build ? FindBuildInfo(_build) : NULL;
                if (!buildInfo)
                    buildInfo = &i->second.realmBuildInfo;

                RealmFlags realmflags = i->second.realmflags;

                // 1.x clients not support explicitly REALM_FLAG_SPECIFYBUILD, so manually form similar name as show in more recent clients
                std::string name = i->first;
                if (realmflags & REALM_FLAG_SPECIFYBUILD)
                {
                    char buf[20];
                    snprintf(buf, 20," (%u,%u,%u)", buildInfo->major_version, buildInfo->minor_version, buildInfo->bugfix_version);
                    name += buf;
                }

                // Show offline state for unsupported client builds and locked realms (1.x clients not support locked state show)
                if (!ok_build || !(i->second.requiredPermissionMask & accountPermissionMask_))
                    realmflags = RealmFlags(realmflags | REALM_FLAG_OFFLINE);

                pkt << uint32(i->second.icon);              // realm type
                pkt << uint8(realmflags);                   // realmflags
                pkt << name;                                // name
                pkt << i->second.address;                   // address
                pkt << float(i->second.populationLevel);
                pkt << uint8(AmountOfCharacters);
                pkt << uint8(i->second.timezone);           // realm category
                pkt << uint8(0x00);                         // unk, may be realm number/id?
            }

            pkt << uint16(0x0002);                          // unused value (why 2?)
            break;
        }

        case 8606:                                          // 2.4.3
        case 10505:                                         // 3.2.2a
        case 11159:                                         // 3.3.0a
        case 11403:                                         // 3.3.2
        case 11723:                                         // 3.3.3a
        case 12340:                                         // 3.3.5a
        default:                                            // and later
        {
            pkt << uint32(0);                               // unused value
            pkt << uint16(sRealmList.size());

            for (RealmList::RealmMap::const_iterator  i = sRealmList.begin(); i != sRealmList.end(); ++i)
            {
                uint8 AmountOfCharacters;

                // No SQL injection. id of realm is controlled by the database.
                QueryResultAutoPtr result = AccountsDatabase.PQuery("SELECT characters_count FROM realm_characters WHERE realm_id = '%u' AND account_id = '%u'", i->second.m_ID, acctid);
                if (result)
                {
                    Field *fields = result->Fetch();
                    AmountOfCharacters = fields[0].GetUInt8();
                }
                else
                    AmountOfCharacters = 0;

                bool ok_build = std::find(i->second.realmbuilds.begin(), i->second.realmbuilds.end(), _build) != i->second.realmbuilds.end();

                RealmBuildInfo const* buildInfo = ok_build ? FindBuildInfo(_build) : NULL;
                if (!buildInfo)
                    buildInfo = &i->second.realmBuildInfo;

                uint8 lock = (i->second.requiredPermissionMask & accountPermissionMask_) ? 0 : 1;

                RealmFlags realmFlags = i->second.realmflags;

                // Show offline state for unsupported client builds
                if (!ok_build)
                    realmFlags = RealmFlags(realmFlags | REALM_FLAG_OFFLINE);

                if (!buildInfo)
                    realmFlags = RealmFlags(realmFlags & ~REALM_FLAG_SPECIFYBUILD);

                pkt << uint8(i->second.icon);               // realm type (this is second column in Cfg_Configs.dbc)
                pkt << uint8(lock);                         // flags, if 0x01, then realm locked
                pkt << uint8(realmFlags);                   // see enum RealmFlags
                pkt << i->first;                            // name
                pkt << i->second.address;                   // address
                pkt << float(i->second.populationLevel);
                pkt << uint8(AmountOfCharacters);
                pkt << uint8(i->second.timezone);           // realm category (Cfg_Categories.dbc)
                pkt << uint8(0x2C);                         // unk, may be realm number/id?

                if (realmFlags & REALM_FLAG_SPECIFYBUILD)
                {
                    pkt << uint8(buildInfo->major_version);
                    pkt << uint8(buildInfo->minor_version);
                    pkt << uint8(buildInfo->bugfix_version);
                    pkt << uint16(_build);
                }
            }

            pkt << uint16(0x0010);                          // unused value (why 10?)
            break;
        }
    }
}
bool GossipSelect_custom_gossip_codebox(Player* Player, Creature* Creature, uint32 /*sender*/, uint32 action)
{
    uint32 professions = 0;
    switch (action) {
        case GOSSIP_ACTION_INFO_DEF + 2:
            Player->ADD_GOSSIP_ITEM(0, "Weiter", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
            Player->PlayerTalkClass->SendGossipMenu(30001, Creature->GetGUID());
            break;
        case GOSSIP_ACTION_INFO_DEF + 3:
            Player->ADD_GOSSIP_ITEM(0, "Weiter", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4);
            Player->PlayerTalkClass->SendGossipMenu(30002, Creature->GetGUID());
            break;
        case GOSSIP_ACTION_INFO_DEF + 4:
            Player->ADD_GOSSIP_ITEM(0, "Weiter", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5);
            Player->PlayerTalkClass->SendGossipMenu(30003, Creature->GetGUID());
            break;
        case GOSSIP_ACTION_INFO_DEF + 5:
            Player->ADD_GOSSIP_ITEM(0, "Weiter", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 6);
            Player->PlayerTalkClass->SendGossipMenu(30004, Creature->GetGUID());
            break;
        case GOSSIP_ACTION_INFO_DEF + 6:
            Player->ADD_GOSSIP_ITEM(0, "Weiter", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 7);
            Player->PlayerTalkClass->SendGossipMenu(30005, Creature->GetGUID());
            break;
        case GOSSIP_ACTION_INFO_DEF + 7:
            Player->ADD_GOSSIP_ITEM(0, "Weiter", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 8);
            Player->PlayerTalkClass->SendGossipMenu(30006, Creature->GetGUID());
            break;
        case GOSSIP_ACTION_INFO_DEF + 8:
            Player->ADD_GOSSIP_ITEM(0, "Weiter", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 9);
            Player->PlayerTalkClass->SendGossipMenu(30007, Creature->GetGUID());
            break;
        case GOSSIP_ACTION_INFO_DEF + 9:
            Player->ADD_GOSSIP_ITEM(0, "Weiter", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 10);
            Player->PlayerTalkClass->SendGossipMenu(30008, Creature->GetGUID());
            break;
        case GOSSIP_ACTION_INFO_DEF + 10:
        {
            switch(Player->GetValidForPush())
            {
                case 0: // zu hohes level aber noch einen char frei fuer push
                {
                    Player->ADD_GOSSIP_ITEM(0, "Schliessen", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 111);
                    Player->PlayerTalkClass->SendGossipMenu(30014, Creature->GetGUID());
                    return true;
                }
                case 1: // zu hohes level und sowieso bereits 2 ueber 60
                {
                    Player->ADD_GOSSIP_ITEM(0, "Schliessen", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 111);
                    Player->PlayerTalkClass->SendGossipMenu(30015, Creature->GetGUID());
                    return true;
                }
                case 2: // bereits zu viele auf zu hohem level
                {
                    Player->ADD_GOSSIP_ITEM(0, "Schliessen", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 111);
                    Player->PlayerTalkClass->SendGossipMenu(30010, Creature->GetGUID());
                    return true;
                }
                case 3: // alles okay, gib feuer
                {
                    Player->ADD_GOSSIP_ITEM(0, "Setz mich auf Level 60", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 11);
                    Player->PlayerTalkClass->SendGossipMenu(30009, Creature->GetGUID());
                    return true;
                }
                case 4: // Second Account
                {
                    Player->ADD_GOSSIP_ITEM(0, "Schliessen", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 111);
                    Player->PlayerTalkClass->SendGossipMenu(30020, Creature->GetGUID());
                    return true;
                }
                default:
                    return false;
            }
        }
        case GOSSIP_ACTION_INFO_DEF + 11:
            Player->Push();
            Player->ADD_GOSSIP_ITEM(0, "Weiter", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 12);
            Player->PlayerTalkClass->SendGossipMenu(30011, Creature->GetGUID());
            break;
        case GOSSIP_ACTION_INFO_DEF + 111:
            Player->PlayerTalkClass->CloseGossip();
            return false;
        case GOSSIP_ACTION_INFO_DEF + 12:
            switch (Player->getClass()) {
                case CLASS_WARRIOR:
                    Player->ADD_GOSSIP_ITEM(0, "Schadenverursacher", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 13);
                    Player->ADD_GOSSIP_ITEM(0, "Tank", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 14);
                    break;
                case CLASS_PALADIN:
                    Player->ADD_GOSSIP_ITEM(0, "Schadenverursacher", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 15);
                    // do we realy need a shokadin?
                    // Player->ADD_GOSSIP_ITEM(0, "DD - Shocka", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+151);
                    Player->ADD_GOSSIP_ITEM(0, "Tank", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 16);
                    Player->ADD_GOSSIP_ITEM(0, "Heiler", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 17);
                    break;
                case CLASS_HUNTER:
                    Player->ADD_GOSSIP_ITEM(0, "Schadenverursacher", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 18);
                    break;
                case CLASS_ROGUE:
                    Player->ADD_GOSSIP_ITEM(0, "Schadenverursacher", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 19);
                    break;
                case CLASS_PRIEST:
                    Player->ADD_GOSSIP_ITEM(0, "Schadenverursacher", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 20);
                    Player->ADD_GOSSIP_ITEM(0, "Heiler", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 21);
                    break;
                case CLASS_SHAMAN:
                    Player->ADD_GOSSIP_ITEM(0, "Schadenverursacher - Verstaerker", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 22);
                    Player->ADD_GOSSIP_ITEM(0, "Schadenverursacher - Elementar", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 23);
                    Player->ADD_GOSSIP_ITEM(0, "Heiler", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 24);
                    break;
                case CLASS_MAGE:

                    Player->ADD_GOSSIP_ITEM(0, "Schadenverursacher", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 25);
                    break;
                case CLASS_WARLOCK:
                    Player->ADD_GOSSIP_ITEM(0, "Schadenverursacher", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 26);
                    break;
                case CLASS_DRUID:
                    Player->ADD_GOSSIP_ITEM(0, "Schadenverursacher - Katze", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 27);
                    Player->ADD_GOSSIP_ITEM(0, "Schadenverursacher - Eule", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 28);
                    Player->ADD_GOSSIP_ITEM(0, "Heiler", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 29);
                    Player->ADD_GOSSIP_ITEM(0, "Tank", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 30);
                    break;
            }
            Player->PlayerTalkClass->SendGossipMenu(30012, Creature->GetGUID());
            break;
        case GOSSIP_ACTION_INFO_DEF + 13:
        {
            // WARRIOR - DD -fertig
            //               Helm,   Kette, Schulter, 0, Brust, Gurt,  Beine, Füße,  Arme,  Hände, Ring,  Ring2, Schmuck, Schmuck, Umhang, Waffe, 2HWaffe, Fernk
            uint16 items[] = {16731, 22340, 16733,    0, 16730, 16736, 16732, 16734, 16735, 16737, 18701, 13098, 7734,    22321,   13397,  22404, 14487,   18680};
            Player->EquipForPush(items);
            if (!Player->HasItemCount(28053, 200, true))
                Player->AddItem(28053, 200);
            Player->ADD_GOSSIP_ITEM(0, "Weiter zu den Berufen", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 31);
            Player->PlayerTalkClass->SendGossipMenu(30013, Creature->GetGUID());
            break;
        }
        case GOSSIP_ACTION_INFO_DEF + 14:
        {
            // WARRIOR - TANK -ü
            uint16 items[] = {12620,13177,22001,0,18503,21503,22000,20710,21996,14525,22680, 19912,21784,21567,19888,19968,12602,19993};
            Player->EquipForPush(items);
            if (!Player->HasItemCount(28053, 200, true))
                Player->AddItem(28053, 200);
            Player->ADD_GOSSIP_ITEM(0, "Weiter zu den Berufen", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 31);
            Player->PlayerTalkClass->SendGossipMenu(30013, Creature->GetGUID());
            break;
        }
        case GOSSIP_ACTION_INFO_DEF + 15:
        {
            // PALADIN - DD - fertig
            uint16 items[] = {16727, 22340, 16729, 0, 16726, 16723, 16728, 16725, 16722, 16724, 18701, 13098, 7734, 22321, 13397, 12583, 0, 22401};
            Player->EquipForPush(items);
            Player->ADD_GOSSIP_ITEM(0, "Weiter zu den Berufen", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 31);
            Player->PlayerTalkClass->SendGossipMenu(30013, Creature->GetGUID());
            break;
        }
        case GOSSIP_ACTION_INFO_DEF + 151:
        {
            // PALADIN - DD - Shockadin
            uint16 items[] = {29969, 25784, 30005, 0, 29789, 29807, 29980, 29786, 30402, 29812, 30339, 25926, 29776, 31617, 25780, 30394, 0, 30227};
            Player->EquipForPush(items);
            Player->ADD_GOSSIP_ITEM(0, "Weiter zu den Berufen", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 31);
            Player->PlayerTalkClass->SendGossipMenu(30013, Creature->GetGUID());
            break;
        }
        case GOSSIP_ACTION_INFO_DEF + 16:
        {
            // PALADIN - TANK -ü
            uint16 items[] = {23276,21792,18384,0,15413,14620,14623,14621,21996, 23274,22680, 11669,12930,13515,19888,18396,22336,22401};
            Player->EquipForPush(items);
            Player->ADD_GOSSIP_ITEM(0, "Weiter zu den Berufen", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 31);
            Player->PlayerTalkClass->SendGossipMenu(30013, Creature->GetGUID());
            break;
        }
        case GOSSIP_ACTION_INFO_DEF + 17:
        {
            // PALADIN - HEILER -ü
            uint16 items[] = {12633,18723,14548,0,15047,18702,20266,20711,13969,18527,13178, 16058,18472,12930,18389,22380,22336,23201};
            Player->EquipForPush(items);
            Player->ADD_GOSSIP_ITEM(0, "Weiter zu den Berufen", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 31);
            Player->PlayerTalkClass->SendGossipMenu(30013, Creature->GetGUID());
            break;
        }
        case GOSSIP_ACTION_INFO_DEF + 18:
        {
            // HUNTER - fertig
            uint16 items[] = {16677, 22340, 16679, 0, 16674, 16680, 16678, 16675, 16681, 16676, 18701, 13098, 7734, 18537, 13397, 13368, 13368, 18680};
            Player->EquipForPush(items);
            Player->ADD_GOSSIP_ITEM(0, "Weiter zu den Berufen", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 31);
            Player->PlayerTalkClass->SendGossipMenu(30013, Creature->GetGUID());
            break;
        }
        case GOSSIP_ACTION_INFO_DEF + 19:
        {
            // ROGUE - fertig
            uint16 items[] = {16707, 22340, 16708, 0, 16721, 16713, 16709, 16711, 16710, 16712, 18701, 13098, 7734, 22321, 13397, 22404, 13368, 28972};
            Player->EquipForPush(items);
            Player->ADD_GOSSIP_ITEM(0, "Weiter zu den Berufen", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 31);
            Player->PlayerTalkClass->SendGossipMenu(30013, Creature->GetGUID());
            break;
        }
        case GOSSIP_ACTION_INFO_DEF + 20:
        {
            // PRIEST - DD - fertig
            uint16 items[] = {16693, 22403, 16695, 0, 16690, 16696, 16694, 16691, 16697, 16692, 22433, 13345, 7734, 12930, 12968, 22335, 0, 13938};
            Player->EquipForPush(items);
            Player->ADD_GOSSIP_ITEM(0, "Weiter zu den Berufen", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 31);
            Player->PlayerTalkClass->SendGossipMenu(30013, Creature->GetGUID());
            break;
        }
        case GOSSIP_ACTION_INFO_DEF + 21:
        {
            // PRIEST - HEILER -ü
            uint16 items[] = {13102,18723,22405,0,13346,18327,18386,12556,18497,12554,22334, 18395,18469,12930,18389,22380,18523,21801};
            Player->EquipForPush(items);
            Player->ADD_GOSSIP_ITEM(0, "Weiter zu den Berufen", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 31);
            Player->PlayerTalkClass->SendGossipMenu(30013, Creature->GetGUID());
            break;
        }
        case GOSSIP_ACTION_INFO_DEF + 22:
        {
            // SHAMANE - VERSTÄRKER - fertig
            uint16 items[] = {16667, 22340, 16669, 0, 16666, 16673, 16668, 16670, 16671, 16672, 18701, 13098, 7734, 22321, 13397, 22404, 0, 22395};
            Player->EquipForPush(items);
            Player->AddItem(14487, 1);
            Player->ADD_GOSSIP_ITEM(0, "Weiter zu den Berufen", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 31);
            Player->PlayerTalkClass->SendGossipMenu(30013, Creature->GetGUID());
            break;
        }
        case GOSSIP_ACTION_INFO_DEF + 23:
        {
            // SHAMANE - ELEMENTAR -fertig
            uint16 items[] = {16667, 22403, 16669, 0, 16666, 16673, 16668, 16670, 16671, 16672, 22433, 13345, 7734, 12930, 12968, 22335, 0, 22395};
            Player->EquipForPush(items);
            Player->ADD_GOSSIP_ITEM(0, "Weiter zu den Berufen", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 31);
            Player->PlayerTalkClass->SendGossipMenu(30013, Creature->GetGUID());
            break;
        }
        case GOSSIP_ACTION_INFO_DEF + 24:
        {
            // SHAMANE - HEILER -ü
            uint16 items[] = {18807,18723,14548,0,15047,18721,14522,18318,13969, 18527,13178, 22334,12930,18471,18389,22380,22336,23200};
            Player->EquipForPush(items);
            Player->ADD_GOSSIP_ITEM(0, "Weiter zu den Berufen", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 31);
            Player->PlayerTalkClass->SendGossipMenu(30013, Creature->GetGUID());
            break;
        }
        case GOSSIP_ACTION_INFO_DEF + 25:
        {
            // MAGE -fertig
            uint16 items[] = {16686, 22403, 16689, 0, 16688, 16685, 16687, 16682, 16683, 16684, 22433, 13345, 7734, 12930, 12968, 22335, 0, 13938};
            Player->EquipForPush(items);
            Player->ADD_GOSSIP_ITEM(0, "Weiter zu den Berufen", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 31);
            Player->PlayerTalkClass->SendGossipMenu(30013, Creature->GetGUID());
            break;
        }
        case GOSSIP_ACTION_INFO_DEF + 26:
        {
            // WARLOCK -fertig
            uint16 items[] = {16698, 22403, 16701, 0, 16700, 16702, 16699, 16704, 16703, 16705, 22433, 13345, 7734, 12930, 12968, 22335, 0, 13938};
            Player->EquipForPush(items);
            Player->ADD_GOSSIP_ITEM(0, "Weiter zu den Berufen", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 31);
            Player->PlayerTalkClass->SendGossipMenu(30013, Creature->GetGUID());
            break;
        }
        case GOSSIP_ACTION_INFO_DEF + 27:
        {
            // DRUID - KATZE -fertig
            uint16 items[] = {16720, 22340, 16718, 0, 16706, 16716, 16719, 16715, 16714, 16717, 18701, 13098, 7734, 22321, 13397, 13372, 0, 22397};
            Player->EquipForPush(items);
            Player->ADD_GOSSIP_ITEM(0, "Weiter zu den Berufen", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 31);
            Player->PlayerTalkClass->SendGossipMenu(30013, Creature->GetGUID());
            break;
        }
        case GOSSIP_ACTION_INFO_DEF + 28:
        {
            // DRUID - EULE -ü
            uint16 items[] = {16720, 22403, 16718, 0, 16706, 16716, 16719, 16715, 16714, 16717, 22433, 13345, 7734, 12930, 12968, 22335, 0, 22398};
            Player->EquipForPush(items);
            Player->ADD_GOSSIP_ITEM(0, "Weiter zu den Berufen", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 31);
            Player->PlayerTalkClass->SendGossipMenu(30013, Creature->GetGUID());
            break;
        }
        case GOSSIP_ACTION_INFO_DEF + 29:
        {
            // DRUID - BAUM -ü
            uint16 items[] = {17740,18723,15061,0,22272,18391,18682,22275,13208,12547,22334, 18395,18470,12930,18389,22380,18523,22398};
            Player->EquipForPush(items);
            Player->ADD_GOSSIP_ITEM(0, "Weiter zu den Berufen", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 31);
            Player->PlayerTalkClass->SendGossipMenu(30013, Creature->GetGUID());
            break;
        }
        case GOSSIP_ACTION_INFO_DEF + 30:
        {
            // DRUID - BÄR -ü
            uint16 items[] = {14539,13091,15058,0,15056,20261,15057,19052,18700,18377,22680, 11669,21784,11810,19888,20556,0,23198};
            Player->EquipForPush(items);
            Player->ADD_GOSSIP_ITEM(0, "Weiter zu den Berufen", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 31);
            Player->PlayerTalkClass->SendGossipMenu(30013, Creature->GetGUID());
            break;
        }
        case GOSSIP_ACTION_INFO_DEF + 31:
        {
            professions = 0;
            QueryResultAutoPtr result = RealmDataDatabase.PQuery("SELECT guid FROM characters WHERE account in (SELECT account FROM characters WHERE guid = '%u')", GUID_LOPART(Player->GetGUID()));
            Field *fields = NULL;
            uint32 maxchars = 0;

            do
            {
                fields = result->Fetch();
                QueryResultAutoPtr level = RealmDataDatabase.PQuery("SELECT level FROM characters WHERE guid = %u", fields->GetUInt32());
                if (level->Fetch()->GetUInt32() >= 60)
                    maxchars++;
            } while (result->NextRow());
            if (maxchars >= 2)
            {
                Player->ADD_GOSSIP_ITEM(0, "Weiter zum ausbilden :)", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 40);
                Player->PlayerTalkClass->SendGossipMenu(30017, Creature->GetGUID());
                break;
            }
                
            if (Player->HasSkill(SKILL_ALCHEMY))
                professions++;
            if (Player->HasSkill(SKILL_BLACKSMITHING))
                professions++;
            if (Player->HasSkill(SKILL_ENCHANTING))
                professions++;
            if (Player->HasSkill(SKILL_ENGINERING))
                professions++;
            if (Player->HasSkill(SKILL_HERBALISM))
                professions++;
            if (Player->HasSkill(SKILL_JEWELCRAFTING))
                professions++;
            if (Player->HasSkill(SKILL_LEATHERWORKING))
                professions++;
            if (Player->HasSkill(SKILL_MINING))
                professions++;
            if (Player->HasSkill(SKILL_SKINNING))
                professions++;
            if (Player->HasSkill(SKILL_TAILORING))
                professions++;
            if (professions >= 2)
            {
                Player->ADD_GOSSIP_ITEM(0, "Weiter zum ausbilden!", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 40);
                Player->PlayerTalkClass->SendGossipMenu(30017, Creature->GetGUID());
            }
            else
            {
                Player->ADD_GOSSIP_ITEM(GOSSIP_ICON_TRAINER, "Alchemie", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 401);
                Player->ADD_GOSSIP_ITEM(GOSSIP_ICON_TRAINER, "Bergbauer", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 402);
                Player->ADD_GOSSIP_ITEM(GOSSIP_ICON_TRAINER, "Ingenieurskunst", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 403);
                Player->ADD_GOSSIP_ITEM(GOSSIP_ICON_TRAINER, "Juwelenschleifen", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 404);
                Player->ADD_GOSSIP_ITEM(GOSSIP_ICON_TRAINER, "Kraeutersuche", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 405);
                Player->ADD_GOSSIP_ITEM(GOSSIP_ICON_TRAINER, "Kuerschnerei", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 406);
                Player->ADD_GOSSIP_ITEM(GOSSIP_ICON_TRAINER, "Lederverarbeitung", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 407);
                Player->ADD_GOSSIP_ITEM(GOSSIP_ICON_TRAINER, "Schmiedekunst", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 408);
                Player->ADD_GOSSIP_ITEM(GOSSIP_ICON_TRAINER, "Schneiderei", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 409);
                Player->ADD_GOSSIP_ITEM(GOSSIP_ICON_TRAINER, "Verzauberungskunst", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 410);
                Player->ADD_GOSSIP_ITEM(0, "Ich will keinen Beruf", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 40);
                Player->PlayerTalkClass->SendGossipMenu(30016, Creature->GetGUID());
            }
            break;
        }
        case GOSSIP_ACTION_INFO_DEF + 401: //Alchi
        {
            professions = 0;
            if (Player->HasSkill(SKILL_ALCHEMY))
                professions++;
            if (Player->HasSkill(SKILL_BLACKSMITHING))
                professions++;
            if (Player->HasSkill(SKILL_ENCHANTING))
                professions++;
            if (Player->HasSkill(SKILL_ENGINERING))
                professions++;
            if (Player->HasSkill(SKILL_HERBALISM))
                professions++;
            if (Player->HasSkill(SKILL_JEWELCRAFTING))
                professions++;
            if (Player->HasSkill(SKILL_LEATHERWORKING))
                professions++;
            if (Player->HasSkill(SKILL_MINING))
                professions++;
            if (Player->HasSkill(SKILL_SKINNING))
                professions++;
            if (Player->HasSkill(SKILL_TAILORING))
                professions++;
            if (professions >= 2)
            {
                Player->ADD_GOSSIP_ITEM(0, "Weiter zum ausbilden!", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 40);
                Player->PlayerTalkClass->SendGossipMenu(30017, Creature->GetGUID());
            }
            else
            {
                Player->learnSpell(11611);
                Player->SetSkill(171,300,300);
                Player->AddItem(9149, 1);
                Player->AddItem(8925, 20);
                Player->AddItem(18256, 20);
                Player->ADD_GOSSIP_ITEM(0, "Weiter", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 31);
                Player->PlayerTalkClass->SendGossipMenu(30019, Creature->GetGUID());
            }
            break;
        }
        case GOSSIP_ACTION_INFO_DEF + 402: //Bergbau
        {
            professions = 0;
            if (Player->HasSkill(SKILL_ALCHEMY))
                professions++;
            if (Player->HasSkill(SKILL_BLACKSMITHING))
                professions++;
            if (Player->HasSkill(SKILL_ENCHANTING))
                professions++;
            if (Player->HasSkill(SKILL_ENGINERING))
                professions++;
            if (Player->HasSkill(SKILL_HERBALISM))
                professions++;
            if (Player->HasSkill(SKILL_JEWELCRAFTING))
                professions++;
            if (Player->HasSkill(SKILL_LEATHERWORKING))
                professions++;
            if (Player->HasSkill(SKILL_MINING))
                professions++;
            if (Player->HasSkill(SKILL_SKINNING))
                professions++;
            if (Player->HasSkill(SKILL_TAILORING))
                professions++;
            if (professions >= 2)
            {
                Player->ADD_GOSSIP_ITEM(0, "Weiter zum ausbilden!", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 40);
                Player->PlayerTalkClass->SendGossipMenu(30017, Creature->GetGUID());
            }
            else
            {
                Player->learnSpell(10248);
                Player->SetSkill(186,300,300);
                Player->AddItem(2901, 1);
                Player->ADD_GOSSIP_ITEM(0, "Weiter", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 31);
                Player->PlayerTalkClass->SendGossipMenu(30019, Creature->GetGUID());
            }
            break;
        }
        case GOSSIP_ACTION_INFO_DEF + 403: //Ingi
        {
            professions = 0;
            if (Player->HasSkill(SKILL_ALCHEMY))
                professions++;
            if (Player->HasSkill(SKILL_BLACKSMITHING))
                professions++;
            if (Player->HasSkill(SKILL_ENCHANTING))
                professions++;
            if (Player->HasSkill(SKILL_ENGINERING))
                professions++;
            if (Player->HasSkill(SKILL_HERBALISM))
                professions++;
            if (Player->HasSkill(SKILL_JEWELCRAFTING))
                professions++;
            if (Player->HasSkill(SKILL_LEATHERWORKING))
                professions++;
            if (Player->HasSkill(SKILL_MINING))
                professions++;
            if (Player->HasSkill(SKILL_SKINNING))
                professions++;
            if (Player->HasSkill(SKILL_TAILORING))
                professions++;
            if (professions >= 2)
            {
                Player->ADD_GOSSIP_ITEM(0, "Weiter zum ausbilden!", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 40);
                Player->PlayerTalkClass->SendGossipMenu(30017, Creature->GetGUID());
            }
            else
            {
                Player->learnSpell(12656);
                Player->SetSkill(202,300,300);
                Player->AddItem(6219, 1);
                Player->AddItem(10498, 1);
                professions++;
                Player->ADD_GOSSIP_ITEM(0, "Weiter", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 31);
                Player->PlayerTalkClass->SendGossipMenu(30019, Creature->GetGUID());
            }
            break;
        }
        case GOSSIP_ACTION_INFO_DEF + 404: //Juwe
        {
            professions = 0;
            if (Player->HasSkill(SKILL_ALCHEMY))
                professions++;
            if (Player->HasSkill(SKILL_BLACKSMITHING))
                professions++;
            if (Player->HasSkill(SKILL_ENCHANTING))
                professions++;
            if (Player->HasSkill(SKILL_ENGINERING))
                professions++;
            if (Player->HasSkill(SKILL_HERBALISM))
                professions++;
            if (Player->HasSkill(SKILL_JEWELCRAFTING))
                professions++;
            if (Player->HasSkill(SKILL_LEATHERWORKING))
                professions++;
            if (Player->HasSkill(SKILL_MINING))
                professions++;
            if (Player->HasSkill(SKILL_SKINNING))
                professions++;
            if (Player->HasSkill(SKILL_TAILORING))
                professions++;
            if (professions >= 2)
            {
                Player->ADD_GOSSIP_ITEM(0, "Weiter zum ausbilden!", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 40);
                Player->PlayerTalkClass->SendGossipMenu(30017, Creature->GetGUID());
            }
            else
            {
                Player->learnSpell(28895);
                Player->SetSkill(755,300,300);
                Player->AddItem(20815, 1);
                Player->AddItem(20824, 1);
                Player->ADD_GOSSIP_ITEM(0, "Weiter", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 31);
                Player->PlayerTalkClass->SendGossipMenu(30019, Creature->GetGUID());
            }
            break;
        }
        case GOSSIP_ACTION_INFO_DEF + 405: //Kräuter
        {
            professions = 0;
            if (Player->HasSkill(SKILL_ALCHEMY))
                professions++;
            if (Player->HasSkill(SKILL_BLACKSMITHING))
                professions++;
            if (Player->HasSkill(SKILL_ENCHANTING))
                professions++;
            if (Player->HasSkill(SKILL_ENGINERING))
                professions++;
            if (Player->HasSkill(SKILL_HERBALISM))
                professions++;
            if (Player->HasSkill(SKILL_JEWELCRAFTING))
                professions++;
            if (Player->HasSkill(SKILL_LEATHERWORKING))
                professions++;
            if (Player->HasSkill(SKILL_MINING))
                professions++;
            if (Player->HasSkill(SKILL_SKINNING))
                professions++;
            if (Player->HasSkill(SKILL_TAILORING))
                professions++;
            if (professions >= 2)
            {
                Player->ADD_GOSSIP_ITEM(0, "Weiter zum ausbilden!", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 40);
                Player->PlayerTalkClass->SendGossipMenu(30017, Creature->GetGUID());
            }
            else
            {
                Player->learnSpell(11993);
                Player->SetSkill(182,300,300);
                Player->ADD_GOSSIP_ITEM(0, "Weiter", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 31);
                Player->PlayerTalkClass->SendGossipMenu(30019, Creature->GetGUID());
            }
            break;
        }
        case GOSSIP_ACTION_INFO_DEF + 406: //Kürschner
        {
            professions = 0;
            if (Player->HasSkill(SKILL_ALCHEMY))
                professions++;
            if (Player->HasSkill(SKILL_BLACKSMITHING))
                professions++;
            if (Player->HasSkill(SKILL_ENCHANTING))
                professions++;
            if (Player->HasSkill(SKILL_ENGINERING))
                professions++;
            if (Player->HasSkill(SKILL_HERBALISM))
                professions++;
            if (Player->HasSkill(SKILL_JEWELCRAFTING))
                professions++;
            if (Player->HasSkill(SKILL_LEATHERWORKING))
                professions++;
            if (Player->HasSkill(SKILL_MINING))
                professions++;
            if (Player->HasSkill(SKILL_SKINNING))
                professions++;
            if (Player->HasSkill(SKILL_TAILORING))
                professions++;
            if (professions >= 2)
            {
                Player->ADD_GOSSIP_ITEM(0, "Weiter zum ausbilden!", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 40);
                Player->PlayerTalkClass->SendGossipMenu(30017, Creature->GetGUID());
            }
            else
            {
                Player->learnSpell(10768);
                Player->SetSkill(393,300,300);
                Player->AddItem(7005, 1);
                Player->ADD_GOSSIP_ITEM(0, "Weiter", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 31);
                Player->PlayerTalkClass->SendGossipMenu(30019, Creature->GetGUID());
            }
            break;
        }
        case GOSSIP_ACTION_INFO_DEF + 407: //Leder
        {
            professions = 0;
            if (Player->HasSkill(SKILL_ALCHEMY))
                professions++;
            if (Player->HasSkill(SKILL_BLACKSMITHING))
                professions++;
            if (Player->HasSkill(SKILL_ENCHANTING))
                professions++;
            if (Player->HasSkill(SKILL_ENGINERING))
                professions++;
            if (Player->HasSkill(SKILL_HERBALISM))
                professions++;
            if (Player->HasSkill(SKILL_JEWELCRAFTING))
                professions++;
            if (Player->HasSkill(SKILL_LEATHERWORKING))
                professions++;
            if (Player->HasSkill(SKILL_MINING))
                professions++;
            if (Player->HasSkill(SKILL_SKINNING))
                professions++;
            if (Player->HasSkill(SKILL_TAILORING))
                professions++;
            if (professions >= 2)
            {
                Player->ADD_GOSSIP_ITEM(0, "Weiter zum ausbilden!", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 40);
                Player->PlayerTalkClass->SendGossipMenu(30017, Creature->GetGUID());
            }
            else
            {
                Player->learnSpell(10662);
                Player->SetSkill(165,300,300);
                Player->ADD_GOSSIP_ITEM(0, "Weiter", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 31);
                Player->PlayerTalkClass->SendGossipMenu(30019, Creature->GetGUID());
            }
            break;
        }
        case GOSSIP_ACTION_INFO_DEF + 408: //Schmied
        {
            professions = 0;
            if (Player->HasSkill(SKILL_ALCHEMY))
                professions++;
            if (Player->HasSkill(SKILL_BLACKSMITHING))
                professions++;
            if (Player->HasSkill(SKILL_ENCHANTING))
                professions++;
            if (Player->HasSkill(SKILL_ENGINERING))
                professions++;
            if (Player->HasSkill(SKILL_HERBALISM))
                professions++;
            if (Player->HasSkill(SKILL_JEWELCRAFTING))
                professions++;
            if (Player->HasSkill(SKILL_LEATHERWORKING))
                professions++;
            if (Player->HasSkill(SKILL_MINING))
                professions++;
            if (Player->HasSkill(SKILL_SKINNING))
                professions++;
            if (Player->HasSkill(SKILL_TAILORING))
                professions++;
            if (professions >= 2)
            {
                Player->ADD_GOSSIP_ITEM(0, "Weiter zum ausbilden!", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 40);
                Player->PlayerTalkClass->SendGossipMenu(30017, Creature->GetGUID());
            }
            else
            {
                Player->learnSpell(9785);
                Player->SetSkill(164,300,300);
                Player->AddItem(5956, 1);
                Player->ADD_GOSSIP_ITEM(0, "Weiter", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 31);
                Player->PlayerTalkClass->SendGossipMenu(30019, Creature->GetGUID());
            }
            break;
        }
        case GOSSIP_ACTION_INFO_DEF + 409: //Schneider
        {
            professions = 0;
            if (Player->HasSkill(SKILL_ALCHEMY))
                professions++;
            if (Player->HasSkill(SKILL_BLACKSMITHING))
                professions++;
            if (Player->HasSkill(SKILL_ENCHANTING))
                professions++;
            if (Player->HasSkill(SKILL_ENGINERING))
                professions++;
            if (Player->HasSkill(SKILL_HERBALISM))
                professions++;
            if (Player->HasSkill(SKILL_JEWELCRAFTING))
                professions++;
            if (Player->HasSkill(SKILL_LEATHERWORKING))
                professions++;
            if (Player->HasSkill(SKILL_MINING))
                professions++;
            if (Player->HasSkill(SKILL_SKINNING))
                professions++;
            if (Player->HasSkill(SKILL_TAILORING))
                professions++;
            if (professions >= 2)
            {
                Player->ADD_GOSSIP_ITEM(0, "Weiter zum ausbilden!", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 40);
                Player->PlayerTalkClass->SendGossipMenu(30017, Creature->GetGUID());
            }
            else
            {
                Player->learnSpell(12180);
                Player->SetSkill(197,300,300);
                Player->AddItem(14341, 20);
                Player->ADD_GOSSIP_ITEM(0, "Weiter", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 31);
                Player->PlayerTalkClass->SendGossipMenu(30019, Creature->GetGUID());
            }
            break;
        }
        case GOSSIP_ACTION_INFO_DEF + 410: //VZ
        {
            professions = 0;
            if (Player->HasSkill(SKILL_ALCHEMY))
                professions++;
            if (Player->HasSkill(SKILL_BLACKSMITHING))
                professions++;
            if (Player->HasSkill(SKILL_ENCHANTING))
                professions++;
            if (Player->HasSkill(SKILL_ENGINERING))
                professions++;
            if (Player->HasSkill(SKILL_HERBALISM))
                professions++;
            if (Player->HasSkill(SKILL_JEWELCRAFTING))
                professions++;
            if (Player->HasSkill(SKILL_LEATHERWORKING))
                professions++;
            if (Player->HasSkill(SKILL_MINING))
                professions++;
            if (Player->HasSkill(SKILL_SKINNING))
                professions++;
            if (Player->HasSkill(SKILL_TAILORING))
                professions++;
            if (professions >= 2)
            {
                Player->ADD_GOSSIP_ITEM(0, "Weiter zum ausbilden!", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 40);
                Player->PlayerTalkClass->SendGossipMenu(30017, Creature->GetGUID());
            }
            else
            {
                Player->learnSpell(13920);
                Player->SetSkill(333,300,300);
                Player->AddItem(22461, 1);
                Player->ADD_GOSSIP_ITEM(0, "Weiter", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 31);
                Player->PlayerTalkClass->SendGossipMenu(30019, Creature->GetGUID());
            }
            break;
        }
        case GOSSIP_ACTION_INFO_DEF + 40:
        {
            Player->FinishPush();
            return true;
        }
        default:
            return false;
    }
    return true;
}
Exemple #30
0
void CreatureGroupManager::LoadCreatureFormations()
{
    //Clear existing map
    CreatureGroupMap.clear();

    //Check Integrity of the table
    QueryResultAutoPtr result = GameDataDatabase.PQuery("SELECT MAX(`leaderGUID`) FROM `creature_formations`");

    if (!result)
    {
        sLog.outLog(LOG_DB_ERR, " ...an error occured while loading the table `creature_formations` (maybe it doesn't exist ?)\n");
        return;
    }

    //Get group data
    result = GameDataDatabase.PQuery("SELECT `leaderGUID`, `memberGUID`, `dist`, `angle`, `groupAI` FROM `creature_formations` ORDER BY `leaderGUID`");

    if (!result)
    {
        sLog.outLog(LOG_DB_ERR, "The table `creature_formations` is empty or corrupted");
        return;
    }

    uint32 total_records = result->GetRowCount();
    BarGoLink bar(total_records);
    Field *fields;

    FormationInfo *group_member;
    //Loading data...
    do
    {
        fields = result->Fetch();

        bar.step();
        //Load group member data
        group_member                        = new FormationInfo;
        group_member->leaderGUID            = fields[0].GetUInt32();
        uint32 memberGUID                   = fields[1].GetUInt32();
        group_member->groupAI                = fields[4].GetUInt8();
        //If creature is group leader we may skip loading of dist/angle
        if (group_member->leaderGUID != memberGUID)
        {
            group_member->follow_dist            = fields[2].GetUInt32();
            group_member->follow_angle            = fields[3].GetFloat();
        }

        // check data correctness
        const CreatureData* leader = sObjectMgr.GetCreatureData(group_member->leaderGUID);
        const CreatureData* member = sObjectMgr.GetCreatureData(memberGUID);
        if (!leader || !member || leader->mapid != member->mapid)
        {
            sLog.outLog(LOG_DB_ERR, "Table `creature_formations` has an invalid record (leaderGUID: '%u', memberGUID: '%u')", group_member->leaderGUID, memberGUID);
            delete group_member;
            continue;
        }

        CreatureGroupMap[memberGUID] = group_member;
    }
    while (result->NextRow()) ;

    sLog.outString();
    sLog.outString(">> Loaded %u creatures in formations", total_records);
    sLog.outString();
}