void SearchStoreHandler::processSearchOpen(Net::MessageIn &msg)
{
    UNIMPLIMENTEDPACKET;
    msg.readInt16("effect");
    msg.readUInt8("uses");
}
Exemple #2
0
void TradeHandler::handleMessage(Net::MessageIn &msg)
{
    switch (msg.getId())
    {
        case GPMSG_TRADE_REQUEST:
        {
            Being *being = actorSpriteManager->findBeing(msg.readInt16());
            if (!being || !mAcceptTradeRequests)
            {
                respond(false);
                break;
            }
            mTrading = true;
            tradePartnerName = being->getName();
            tradePartnerID = being->getId();
            ConfirmDialog *dlg = new ConfirmDialog(_("Request for Trade"),
                    strprintf(_("%s wants to trade with you, do you accept?"),
                            tradePartnerName.c_str()));
            dlg->addActionListener(&listener);
        }   break;

        case GPMSG_TRADE_ADD_ITEM:
        {
            int type = msg.readInt16();
            int amount = msg.readInt8();
            tradeWindow->addItem(type, false, amount);
        }   break;

        case GPMSG_TRADE_SET_MONEY:
            tradeWindow->setMoney(msg.readInt32());
            break;

        case GPMSG_TRADE_START:
            tradeWindow->reset();
            tradeWindow->setCaption(strprintf(_("Trading with %s"),
                                              tradePartnerName.c_str()));
            tradeWindow->setVisible(true);
            break;

        case GPMSG_TRADE_BOTH_CONFIRM:
            tradeWindow->receivedOk(false);
            break;

        case GPMSG_TRADE_AGREED:
            tradeWindow->receivedOk(false);
            break;

        case GPMSG_TRADE_CANCEL:
            SERVER_NOTICE(_("Trade canceled."))
            tradeWindow->setVisible(false);
            tradeWindow->reset();
            mTrading = false;
            break;

        case GPMSG_TRADE_COMPLETE:
            SERVER_NOTICE(_("Trade completed."))
            tradeWindow->setVisible(false);
            tradeWindow->reset();
            mTrading = false;
            break;
    }
}
Exemple #3
0
void PartyHandler::processPartySettings(Net::MessageIn &msg)
{
    if (!Ea::partyTab)
    {
        if (!chatWindow)
            return;

        Ea::partyTab = new PartyTab();
        Ea::partyTab->loadFromLogFile("#Party");
    }

    // These seem to indicate the sharing mode for exp and items
    short exp = msg.readInt16();
    short item = msg.readInt16();

    if (!Ea::partyTab)
        return;

    switch (exp)
    {
        case PARTY_SHARE:
            if (mShareExp == PARTY_SHARE)
                break;
            mShareExp = PARTY_SHARE;
            if (Ea::partyTab)
            {
                Ea::partyTab->chatLog(
                    _("Experience sharing enabled."), BY_SERVER);
            }
            break;
        case PARTY_SHARE_NO:
            if (mShareExp == PARTY_SHARE_NO)
                break;
            mShareExp = PARTY_SHARE_NO;
            if (Ea::partyTab)
            {
                Ea::partyTab->chatLog(
                    _("Experience sharing disabled."), BY_SERVER);
            }
            break;
        case PARTY_SHARE_NOT_POSSIBLE:
            if (mShareExp == PARTY_SHARE_NOT_POSSIBLE)
                break;
            mShareExp = PARTY_SHARE_NOT_POSSIBLE;
            if (Ea::partyTab)
            {
                Ea::partyTab->chatLog(
                    _("Experience sharing not possible."),
                    BY_SERVER);
            }
            break;
        default:
            logger->log("QQQ Unknown party exp option: %d\n", exp);
            break;
    }

    switch (item)
    {
        case PARTY_SHARE:
            if (mShareItems == PARTY_SHARE)
                break;
            mShareItems = PARTY_SHARE;
            if (Ea::partyTab)
            {
                Ea::partyTab->chatLog(
                    _("Item sharing enabled."), BY_SERVER);
            }
            break;
        case PARTY_SHARE_NO:
            if (mShareItems == PARTY_SHARE_NO)
                break;
            mShareItems = PARTY_SHARE_NO;
            if (Ea::partyTab)
            {
                Ea::partyTab->chatLog(
                    _("Item sharing disabled."), BY_SERVER);
            }
            break;
        case PARTY_SHARE_NOT_POSSIBLE:
            if (mShareItems == PARTY_SHARE_NOT_POSSIBLE)
                break;
            mShareItems = PARTY_SHARE_NOT_POSSIBLE;
            if (Ea::partyTab)
            {
                Ea::partyTab->chatLog(
                    _("Item sharing not possible."), BY_SERVER);
            }
            break;
        default:
            logger->log("QQQ Unknown party item option: %d\n",
                        exp);
            break;
    }
}
Exemple #4
0
void CharServerHandler::readPlayerData(Net::MessageIn &msg, Net::Character *character)
{
    const Token &token =
            static_cast<LoginHandler*>(Net::getLoginHandler())->getToken();

    LocalPlayer *tempPlayer = new LocalPlayer(msg.readInt32(), 0);
    tempPlayer->setGender(token.sex);

    character->data.mAttributes[EXP] = msg.readInt32();
    character->data.mAttributes[MONEY] = msg.readInt32();
    character->data.mStats[JOB].exp = msg.readInt32();

    int temp = msg.readInt32();
    character->data.mStats[JOB].base = temp;
    character->data.mStats[JOB].mod = temp;

    tempPlayer->setSprite(SPRITE_SHOE, msg.readInt16());
    tempPlayer->setSprite(SPRITE_GLOVES, msg.readInt16());
    tempPlayer->setSprite(SPRITE_CAPE, msg.readInt16());
    tempPlayer->setSprite(SPRITE_MISC1, msg.readInt16());

    msg.readInt32();                       // option
    msg.readInt32();                       // karma
    msg.readInt32();                       // manner
    msg.skip(2);                          // unknown

    character->data.mAttributes[HP] = msg.readInt16();
    character->data.mAttributes[MAX_HP] = msg.readInt16();
    character->data.mAttributes[MP] = msg.readInt16();
    character->data.mAttributes[MAX_MP] = msg.readInt16();

    msg.readInt16();                       // speed
    tempPlayer->setSubtype(msg.readInt16()); // class (used for race)
    int hairStyle = msg.readInt16();
    Uint16 weapon = msg.readInt16();
    tempPlayer->setSprite(SPRITE_WEAPON, weapon, "", true);

    character->data.mAttributes[LEVEL] = msg.readInt16();

    msg.readInt16();                       // skill point
    tempPlayer->setSprite(SPRITE_BOTTOMCLOTHES, msg.readInt16()); // head bottom
    tempPlayer->setSprite(SPRITE_SHIELD, msg.readInt16());
    tempPlayer->setSprite(SPRITE_HAT, msg.readInt16()); // head option top
    tempPlayer->setSprite(SPRITE_TOPCLOTHES, msg.readInt16()); // head option mid
    tempPlayer->setSprite(SPRITE_HAIR, hairStyle * -1,
                          hairDB.getHairColor(msg.readInt16()));
    tempPlayer->setSprite(SPRITE_MISC2, msg.readInt16());
    tempPlayer->setName(msg.readString(24));

    character->dummy = tempPlayer;

    for (int i = 0; i < 6; i++)
        character->data.mStats[i + STRENGTH].base = msg.readInt8();

    character->slot = msg.readInt8(); // character slot
    msg.readInt8();                        // unknown
}
void TradeHandler::handleMessage(Net::MessageIn &msg)
{
    switch (msg.getId())
    {
        case SMSG_TRADE_REQUEST:
                // If a trade window or request window is already open, send a
                // trade cancel to any other trade request.
                //
                // Note that it would be nice if the server would prevent this
                // situation, and that the requesting player would get a
                // special message about the player being occupied.
                tradePartnerName = msg.readString(24);

                if (player_relations.hasPermission(tradePartnerName,
                                                   PlayerRelation::TRADE))
                {
                    if (!player_node->tradeRequestOk())
                    {
                        Net::getTradeHandler()->respond(false);
                        break;
                    }

                    player_node->setTrading(true);
                    ConfirmDialog *dlg;
                    dlg = new ConfirmDialog(_("Request for Trade"),
                            strprintf(_("%s wants to trade with you, do you "
                                    "accept?"), tradePartnerName.c_str()));
                    dlg->addActionListener(&listener);
                }
                else
                {
                    Net::getTradeHandler()->respond(false);
                    break;
                }
            break;

        case SMSG_TRADE_RESPONSE:
            switch (msg.readInt8())
            {
                case 0: // Too far away
                    localChatTab->chatLog(_("Trading isn't possible. Trade "
                            "partner is too far away."), BY_SERVER);
                    break;
                case 1: // Character doesn't exist
                    localChatTab->chatLog(_("Trading isn't possible. Character "
                            "doesn't exist."), BY_SERVER);
                    break;
                case 2: // Invite request check failed...
                    localChatTab->chatLog(_("Trade cancelled due to an unknown "
                            "reason."), BY_SERVER);
                    break;
                case 3: // Trade accepted
                    tradeWindow->reset();
                    tradeWindow->setCaption(strprintf(_("Trade: You and %s"),
                            tradePartnerName.c_str()));
                    tradeWindow->setVisible(true);
                    break;
                case 4: // Trade cancelled
                    if (player_relations.hasPermission(tradePartnerName,
                                                       PlayerRelation::SPEECH_LOG))
                        localChatTab->chatLog(strprintf(_("Trade with %s "
                                "cancelled."), tradePartnerName.c_str()),
                                BY_SERVER);
                    // otherwise ignore silently

                    tradeWindow->setVisible(false);
                    player_node->setTrading(false);
                    break;
                default: // Shouldn't happen as well, but to be sure
                    localChatTab->chatLog(_("Unhandled trade cancel packet."),
                            BY_SERVER);
                    break;
            }
            break;

        case SMSG_TRADE_ITEM_ADD:
            {
                int amount = msg.readInt32();
                int type = msg.readInt16();
                msg.readInt8();  // identified flag
                msg.readInt8();  // attribute
                msg.readInt8();  // refine
                msg.skip(8);     // card (4 shorts)

                // TODO: handle also identified, etc
                if (type == 0) {
                    tradeWindow->setMoney(amount);
                } else {
                    tradeWindow->addItem(type, false, amount, false);
                }
            }
            break;

        case SMSG_TRADE_ITEM_ADD_RESPONSE:
            // Trade: New Item add response (was 0x00ea, now 01b1)
            {
                const int index = msg.readInt16() - INVENTORY_OFFSET;
                Item *item = player_node->getInventory()->getItem(index);
                if (!item)
                {
                    tradeWindow->receivedOk(true);
                    return;
                }
                int quantity = msg.readInt16();

                switch (msg.readInt8())
                {
                    case 0:
                        // Successfully added item
                        if (item->isEquipment() && item->isEquipped())
                        {
                            Net::getInventoryHandler()->unequipItem(item);
                        }
                        tradeWindow->addItem(item->getId(), true, quantity,
                                item->isEquipment());
                        item->increaseQuantity(-quantity);
                        break;
                    case 1:
                        // Add item failed - player overweighted
                        localChatTab->chatLog(_("Failed adding item. Trade "
                                "partner is over weighted."), BY_SERVER);
                        break;
                    case 2:
                         // Add item failed - player has no free slot
                         localChatTab->chatLog(_("Failed adding item. Trade "
                                 "partner has no free slot."), BY_SERVER);
                         break;
                    default:
                        localChatTab->chatLog(_("Failed adding item for "
                                "unknown reason."), BY_SERVER);
                        break;
                }
            }
            break;

        case SMSG_TRADE_OK:
            // 0 means ok from myself, 1 means ok from other;
            tradeWindow->receivedOk(msg.readInt8() == 0);
            break;

        case SMSG_TRADE_CANCEL:
            localChatTab->chatLog(_("Trade canceled."), BY_SERVER);
            tradeWindow->setVisible(false);
            tradeWindow->reset();
            player_node->setTrading(false);
            break;

        case SMSG_TRADE_COMPLETE:
            localChatTab->chatLog(_("Trade completed."), BY_SERVER);
            tradeWindow->setVisible(false);
            tradeWindow->reset();
            player_node->setTrading(false);
            break;
    }
}
void CharServerHandler::readPlayerData(Net::MessageIn &msg,
                                       Net::Character *character,
                                       bool withColors)
{
    if (!character)
        return;

    const Token &token =
        static_cast<LoginHandler*>(Net::getLoginHandler())->getToken();

    LocalPlayer *tempPlayer = new LocalPlayer(msg.readInt32(), 0);
    tempPlayer->setGender(token.sex);

    PlayerInfoBackend &data = character->data;
    data.mAttributes[EXP] = msg.readInt32();
    data.mAttributes[MONEY] = msg.readInt32();
    data.mStats[JOB].exp = msg.readInt32();

    int temp = msg.readInt32();
    data.mStats[JOB].base = temp;
    data.mStats[JOB].mod = temp;

    int shoes = msg.readInt16();
    int gloves = msg.readInt16();
    int cape = msg.readInt16();
    int misc1 = msg.readInt16();

    msg.readInt32();                       // option
    msg.readInt32();                       // karma
    msg.readInt32();                       // manner
    msg.readInt16();                       // character points left

    data.mAttributes[HP] = msg.readInt16();
    data.mAttributes[MAX_HP] = msg.readInt16();
    data.mAttributes[MP] = msg.readInt16();
    data.mAttributes[MAX_MP] = msg.readInt16();

    msg.readInt16();                       // speed
    tempPlayer->setSubtype(msg.readInt16()); // class (used for race)
    int hairStyle = msg.readInt16();
    uint16_t weapon = msg.readInt16();  // server not used it. may be need use?
    tempPlayer->setSprite(SPRITE_WEAPON, weapon, "", 1, true);

    data.mAttributes[LEVEL] = msg.readInt16();

    msg.readInt16();                       // skill point
    int bottomClothes = msg.readInt16();
    int shield = msg.readInt16();

    int hat = msg.readInt16(); // head option top
    int topClothes = msg.readInt16();

    tempPlayer->setSprite(SPRITE_HAIR, hairStyle * -1,
        ItemDB::get(-hairStyle).getDyeColorsString(msg.readInt16()));

    int misc2 = msg.readInt16();
    tempPlayer->setName(msg.readString(24));

    character->dummy = tempPlayer;

    for (int i = 0; i < 6; i++)
        character->data.mStats[i + STR].base = msg.readInt8();

    if (withColors)
    {
        tempPlayer->setSprite(SPRITE_SHOE, shoes, "", msg.readInt8());
        tempPlayer->setSprite(SPRITE_GLOVES, gloves, "", msg.readInt8());
        tempPlayer->setSprite(SPRITE_CAPE, cape, "", msg.readInt8());
        tempPlayer->setSprite(SPRITE_MISC1, misc1, "", msg.readInt8());
        tempPlayer->setSprite(SPRITE_BOTTOMCLOTHES, bottomClothes,
            "", msg.readInt8());
        //to avoid show error (error.xml) need remove this sprite
        if (!config.getBoolValue("hideShield"))
            tempPlayer->setSprite(SPRITE_SHIELD, shield, "", msg.readInt8());
        else
            msg.readInt8();

        tempPlayer->setSprite(SPRITE_HAT, hat, "",
            msg.readInt8()); // head option top
        tempPlayer->setSprite(SPRITE_TOPCLOTHES, topClothes, "",
            msg.readInt8());
        tempPlayer->setSprite(SPRITE_MISC2, misc2, "", msg.readInt8());
        msg.skip(5);
        character->slot = msg.readInt8(); // character slot
    }
    else
    {
        tempPlayer->setSprite(SPRITE_SHOE, shoes);
        tempPlayer->setSprite(SPRITE_GLOVES, gloves);
        tempPlayer->setSprite(SPRITE_CAPE, cape);
        tempPlayer->setSprite(SPRITE_MISC1, misc1);
        tempPlayer->setSprite(SPRITE_BOTTOMCLOTHES, bottomClothes);
        //to avoid show error (error.xml) need remove this sprite
        if (!config.getBoolValue("hideShield"))
            tempPlayer->setSprite(SPRITE_SHIELD, shield);

        tempPlayer->setSprite(SPRITE_HAT, hat); // head option top
        tempPlayer->setSprite(SPRITE_TOPCLOTHES, topClothes);
        tempPlayer->setSprite(SPRITE_MISC2, misc2);
        character->slot = msg.readInt8(); // character slot
    }

    msg.readInt8();                        // unknown
}
void BattleGroundRecv::processBattleUpdateScore(Net::MessageIn &msg)
{
    UNIMPLEMENTEDPACKET;
    msg.readInt16("camp a points");
    msg.readInt16("camp b points");
}
Exemple #8
0
void AuctionRecv::processAuctionClose(Net::MessageIn &msg)
{
    UNIMPLEMENTEDPACKET;
    msg.readInt16("flag");
}
Exemple #9
0
void BeingHandler::handleBeingsMoveMessage(Net::MessageIn &msg)
{
    while (msg.getUnreadLength())
    {
        int id = msg.readInt16();
        int flags = msg.readInt8();
        Being *being = actorSpriteManager->findBeing(id);
        int sx = 0, sy = 0, dx = 0, dy = 0, speed = 0;

        if ((!flags & (MOVING_POSITION | MOVING_DESTINATION)))
            continue;

        if (flags & MOVING_POSITION)
        {
            sx = msg.readInt16();
            sy = msg.readInt16();
        }

        if (flags & MOVING_DESTINATION)
        {
            dx = msg.readInt16();
            dy = msg.readInt16();
            speed = msg.readInt8();
        }

        if (!being)
            continue;

        if (speed)
        {
           /*
            * The being's speed is transfered in tiles per second * 10
            * to keep it transferable in a Byte.
            * We set it back to tiles per second and in a float.
            */
            float speedTilesSeconds = (float) speed / 10;
            being->setMoveSpeed(Vector(speedTilesSeconds, speedTilesSeconds,
                                       0));
        }

        // Ignore messages from the server for the local player
        if (being == player_node)
            continue;

        // If the position differs too much from the actual one, we resync
        // the being position
        if (flags & MOVING_POSITION)
        {
            if (!being->getMap()->containsPixel(sx, sy))
            {
                logger->log("Warning: Received GPMSG_BEINGS_MOVE for being id "
                            "%i with position outside the map boundaries "
                            "(x = %i, y = %i)", id, sx, sy);
                continue;
            }

            Vector serverPos(sx, sy);
            if (serverPos.length()
                - being->getPosition().length() > POSITION_DIFF_TOLERANCE)
                being->setPosition(serverPos);
        }

        if (flags & MOVING_DESTINATION)
        {
            if (!being->getMap()->containsPixel(dx, dy))
            {
                logger->log("Warning: Received GPMSG_BEINGS_MOVE for being id "
                            "%i with destination outside the map boundaries "
                            "(x = %i, y = %i)", id, dx, dy);
                continue;
            }

            being->setDestination(dx, dy);
        }
    }
}
Exemple #10
0
void PlayerHandler::processPlayerUpgradeMessage(Net::MessageIn &msg)
{
    UNIMPLIMENTEDPACKET;
    msg.readInt32("result");
    msg.readInt16("item id");
}
Exemple #11
0
void AuctionRecv::processAuctionSetItem(Net::MessageIn &msg)
{
    UNIMPLEMENTEDPACKET;
    msg.readInt16("index");
    msg.readUInt8("flag");
}
Exemple #12
0
void PlayerHandler::processNotifyMapInfo(Net::MessageIn &msg)
{
    UNIMPLIMENTEDPACKET;
    msg.readInt16("type");
}
Exemple #13
0
void PlayerHandler::processPlayerStatUpdate5(Net::MessageIn &msg)
{
    BLOCK_START("PlayerHandler::processPlayerStatUpdate5")
    PlayerInfo::setAttribute(Attributes::CHAR_POINTS,
        msg.readInt16("char points"));

    unsigned int val = msg.readUInt8("str");
    PlayerInfo::setStatBase(Attributes::STR, val);
    if (statusWindow)
    {
        statusWindow->setPointsNeeded(Attributes::STR,
            msg.readUInt8("str cost"));
    }
    else
    {
        msg.readUInt8("str need");
    }

    val = msg.readUInt8("agi");
    PlayerInfo::setStatBase(Attributes::AGI, val);
    if (statusWindow)
    {
        statusWindow->setPointsNeeded(Attributes::AGI,
            msg.readUInt8("agi cost"));
    }
    else
    {
        msg.readUInt8("agi cost");
    }

    val = msg.readUInt8("vit");
    PlayerInfo::setStatBase(Attributes::VIT, val);
    if (statusWindow)
    {
        statusWindow->setPointsNeeded(Attributes::VIT,
            msg.readUInt8("vit cost"));
    }
    else
    {
        msg.readUInt8("vit cost");
    }

    val = msg.readUInt8("int");
    PlayerInfo::setStatBase(Attributes::INT, val);
    if (statusWindow)
    {
        statusWindow->setPointsNeeded(Attributes::INT,
            msg.readUInt8("int cost"));
    }
    else
    {
        msg.readUInt8("int cost");
    }

    val = msg.readUInt8("dex");
    PlayerInfo::setStatBase(Attributes::DEX, val);
    if (statusWindow)
    {
        statusWindow->setPointsNeeded(Attributes::DEX,
            msg.readUInt8("dex cost"));
    }
    else
    {
        msg.readUInt8("dex cost");
    }

    val = msg.readUInt8("luk");
    PlayerInfo::setStatBase(Attributes::LUK, val);
    if (statusWindow)
    {
        statusWindow->setPointsNeeded(Attributes::LUK,
            msg.readUInt8("luk cost"));
    }
    else
    {
        msg.readUInt8("luk cost");
    }

    PlayerInfo::setStatBase(Attributes::ATK,
        msg.readInt16("left atk"), Notify_false);
    PlayerInfo::setStatMod(Attributes::ATK, msg.readInt16("right atk"));
    PlayerInfo::updateAttrs();

    val = msg.readInt16("right matk");
    PlayerInfo::setStatBase(Attributes::MATK, val, Notify_false);

    val = msg.readInt16("left matk");
    PlayerInfo::setStatMod(Attributes::MATK, val);

    PlayerInfo::setStatBase(Attributes::DEF,
        msg.readInt16("left def"), Notify_false);
    PlayerInfo::setStatMod(Attributes::DEF, msg.readInt16("right def"));

    PlayerInfo::setStatBase(Attributes::MDEF,
        msg.readInt16("left mdef"), Notify_false);
    PlayerInfo::setStatMod(Attributes::MDEF, msg.readInt16("right mdef"));

    PlayerInfo::setStatBase(Attributes::HIT, msg.readInt16("hit"));

    PlayerInfo::setStatBase(Attributes::FLEE,
        msg.readInt16("flee"), Notify_false);
    PlayerInfo::setStatMod(Attributes::FLEE, msg.readInt16("flee2/10"));

    PlayerInfo::setStatBase(Attributes::CRIT, msg.readInt16("crit/10"));

    PlayerInfo::setAttribute(Attributes::ATTACK_DELAY,
        msg.readInt16("attack speed"));
    msg.readInt16("plus speed = 0");

    BLOCK_END("PlayerHandler::processPlayerStatUpdate5")
}
void SearchStoreHandler::processSearchClickAck(Net::MessageIn &msg)
{
    UNIMPLIMENTEDPACKET;
    msg.readInt16("x");
    msg.readInt16("y");
}
Exemple #15
0
void VendingHandler::processReport(Net::MessageIn &msg)
{
    UNIMPLIMENTEDPACKET;
    msg.readInt16("inv index");
    msg.readInt16("amount");
}
void CharServerHandler::readPlayerData(Net::MessageIn &msg,
                                       Net::Character *const character,
                                       const bool withColors) const
{
    if (!character)
        return;

    const Token &token =
        static_cast<LoginHandler*>(loginHandler)->getToken();

    LocalPlayer *const tempPlayer = new LocalPlayer(
        msg.readBeingId("account id"), BeingTypeId_zero);
    tempPlayer->setGender(token.sex);

    PlayerInfoBackend &data = character->data;
    data.mAttributes[Attributes::EXP] = msg.readInt32("exp");
    data.mAttributes[Attributes::MONEY] = msg.readInt32("money");
    Stat &jobStat = data.mStats[Attributes::JOB];
    jobStat.exp = msg.readInt32("job");

    const int temp = msg.readInt32("job level");
    jobStat.base = temp;
    jobStat.mod = temp;

    const int shoes = msg.readInt16("shoes");
    const int gloves = msg.readInt16("gloves");
    const int cape = msg.readInt16("cape");
    const int misc1 = msg.readInt16("misc1");

    msg.readInt32("option");
    tempPlayer->setKarma(msg.readInt32("karma"));
    tempPlayer->setManner(msg.readInt32("manner"));
    msg.readInt16("character points left");

    data.mAttributes[Attributes::HP] = msg.readInt16("hp");
    data.mAttributes[Attributes::MAX_HP] = msg.readInt16("max hp");
    data.mAttributes[Attributes::MP] = msg.readInt16("mp");
    data.mAttributes[Attributes::MAX_MP] = msg.readInt16("max mp");

    msg.readInt16("speed");
    const uint16_t race = msg.readInt16("class");
    const uint8_t hairStyle = msg.readUInt8("hair style");
    const uint16_t look = msg.readUInt8("look");
    tempPlayer->setSubtype(fromInt(race, BeingTypeId), look);
    const uint16_t weapon = msg.readInt16("weapon");
    tempPlayer->setSprite(SPRITE_BODY, weapon, "", 1, true);

    data.mAttributes[Attributes::LEVEL] = msg.readInt16("level");

    msg.readInt16("skill point");
    const int bottomClothes = msg.readInt16("bottom clothes");
    const int shield = msg.readInt16("shield");

    const int hat = msg.readInt16("hat");
    const int topClothes = msg.readInt16("top clothes");

    const uint8_t hairColor = msg.readUInt8("hair color");
    msg.readUInt8("unused");
    tempPlayer->setSprite(SPRITE_HAIR_COLOR, hairStyle * -1,
        ItemDB::get(-hairStyle).getDyeColorsString(hairColor));
    tempPlayer->setHairColor(static_cast<unsigned char>(hairColor));

    const int misc2 = msg.readInt16("misc2");
    tempPlayer->setName(msg.readString(24, "name"));

    character->dummy = tempPlayer;

    character->data.mStats[Attributes::STR].base = msg.readUInt8("str");
    character->data.mStats[Attributes::AGI].base = msg.readUInt8("agi");
    character->data.mStats[Attributes::VIT].base = msg.readUInt8("vit");
    character->data.mStats[Attributes::INT].base = msg.readUInt8("int");
    character->data.mStats[Attributes::DEX].base = msg.readUInt8("dex");
    character->data.mStats[Attributes::LUK].base = msg.readUInt8("luk");

    if (withColors)
    {
        tempPlayer->setSprite(SPRITE_HAIR, shoes, "",
            msg.readUInt8("shoes color"));
        tempPlayer->setSprite(SPRITE_SHOES, gloves, "",
            msg.readUInt8("gloves color"));
        tempPlayer->setSprite(SPRITE_SHIELD, cape, "",
            msg.readUInt8("cape color"));
        tempPlayer->setSprite(SPRITE_HEAD_TOP, misc1, "",
            msg.readUInt8("misc1 color"));
        tempPlayer->setSprite(SPRITE_WEAPON, bottomClothes,
            "", msg.readUInt8("bottom clothes color"));
        tempPlayer->setSprite(SPRITE_FLOOR, shield, "",
            msg.readUInt8("shield color"));
        tempPlayer->setSprite(SPRITE_CLOTHES_COLOR, hat, "",
            msg.readUInt8("head option top color"));
        tempPlayer->setSprite(SPRITE_HEAD_BOTTOM, topClothes, "",
            msg.readUInt8("top clothes color"));
        tempPlayer->setSprite(SPRITE_HEAD_MID, misc2, "",
            msg.readUInt8("misc2 color"));
        msg.skip(5, "unused");
    }
    else
    {
        tempPlayer->setSprite(SPRITE_HAIR, shoes);
        tempPlayer->setSprite(SPRITE_SHOES, gloves);
        tempPlayer->setSprite(SPRITE_SHIELD, cape);
        tempPlayer->setSprite(SPRITE_HEAD_TOP, misc1);
        tempPlayer->setSprite(SPRITE_WEAPON, bottomClothes);
        tempPlayer->setSprite(SPRITE_FLOOR, shield);
        tempPlayer->setSprite(SPRITE_CLOTHES_COLOR, hat);  // head option top
        tempPlayer->setSprite(SPRITE_HEAD_BOTTOM, topClothes);
        tempPlayer->setSprite(SPRITE_HEAD_MID, misc2);
    }
    character->slot = msg.readUInt8("slot");
    msg.readUInt8("unused");
}
Exemple #17
0
void MercenaryRecv::processMercenaryInfo(Net::MessageIn &msg)
{
    if (actorManager == nullptr)
        return;
    // +++ need create if need mercenary being and update stats
    Being *const dstBeing = actorManager->findBeing(
        msg.readBeingId("being id"));
    PlayerInfo::setStatBase(Attributes::MERC_ATK,
        msg.readInt16("atk"),
        Notify_true);
    PlayerInfo::setStatBase(Attributes::MERC_MATK,
        msg.readInt16("matk"),
        Notify_true);
    PlayerInfo::setStatBase(Attributes::MERC_HIT,
        msg.readInt16("hit"),
        Notify_true);
    PlayerInfo::setStatBase(Attributes::MERC_CRIT,
        msg.readInt16("crit/10"),
        Notify_true);
    PlayerInfo::setStatBase(Attributes::MERC_DEF,
        msg.readInt16("def"),
        Notify_true);
    PlayerInfo::setStatBase(Attributes::MERC_MDEF,
        msg.readInt16("mdef"),
        Notify_true);
    PlayerInfo::setStatBase(Attributes::MERC_FLEE,
        msg.readInt16("flee"),
        Notify_true);
    PlayerInfo::setStatBase(Attributes::MERC_ATTACK_DELAY,
        msg.readInt16("attack speed"),
        Notify_true);
    const std::string name = msg.readString(24, "name");
    const int level = msg.readInt16("level");
    PlayerInfo::setStatBase(Attributes::MERC_LEVEL,
        level,
        Notify_true);
    PlayerInfo::setStatBase(Attributes::MERC_HP,
        msg.readInt32("hp"),
        Notify_true);
    PlayerInfo::setStatBase(Attributes::MERC_MAX_HP,
        msg.readInt32("max hp"),
        Notify_true);
    PlayerInfo::setStatBase(Attributes::MERC_MP,
        msg.readInt32("sp"),
        Notify_true);
    PlayerInfo::setStatBase(Attributes::MERC_MAX_MP,
        msg.readInt32("max sp"),
        Notify_true);
    PlayerInfo::setStatBase(Attributes::MERC_EXPIRE,
        msg.readInt32("expire time"),
        Notify_true);
    PlayerInfo::setStatBase(Attributes::MERC_FAITH,
        msg.readInt16("faith"),
        Notify_true);
    PlayerInfo::setStatBase(Attributes::MERC_CALLS,
        msg.readInt32("calls"),
        Notify_true);
    PlayerInfo::setStatBase(Attributes::MERC_KILLS,
        msg.readInt32("kills"),
        Notify_true);
    const int range = msg.readInt16("attack range");
    PlayerInfo::setStatBase(Attributes::MERC_ATTACK_RANGE,
        range,
        Notify_true);
    PlayerInfo::updateAttrs();

    if ((dstBeing != nullptr) && (localPlayer != nullptr))
    {
        MercenaryInfo *const mercenary = new MercenaryInfo;
        mercenary->id = dstBeing->getId();
        mercenary->name = name;
        mercenary->level = level;
        mercenary->range = range;
        PlayerInfo::setMercenary(mercenary);
        PlayerInfo::setMercenaryBeing(dstBeing);
    }
}
Exemple #18
0
void LoginHandler::processCondingKey(Net::MessageIn &msg)
{
    UNIMPLIMENTEDPACKET;
    const int sz = msg.readInt16("len") - 4;
    msg.readString(sz, "coding key");
}
void CharServerHandler::handleMessage(Net::MessageIn &msg)
{
    switch (msg.getId())
    {
        case SMSG_CHAR_LOGIN:
            processCharLogin(msg);
            break;

        case SMSG_CHAR_LOGIN_ERROR:
            processCharLoginError(msg);
            break;

        case SMSG_CHAR_CREATE_SUCCEEDED:
            processCharCreate(msg, false);
            break;

        case SMSG_CHAR_CREATE_SUCCEEDED2:
            processCharCreate(msg, true);
            break;

        case SMSG_CHAR_CREATE_FAILED:
            processCharCreateFailed(msg);
            break;

        case SMSG_CHAR_DELETE_SUCCEEDED:
            processCharDelete(msg);
            break;

        case SMSG_CHAR_DELETE_FAILED:
            processCharDeleteFailed(msg);
            break;

        case SMSG_CHAR_MAP_INFO:
        {
//            msg.skip(4); // CharID, must be the same as player_node->charID
            PlayerInfo::setCharId(msg.readInt32());
            GameHandler *gh = static_cast<GameHandler*>(Net::getGameHandler());
            gh->setMap(msg.readString(16));
            if (config.getBoolValue("usePersistentIP"))
            {
                msg.readInt32();
                mapServer.hostname = Client::getServerName();
            }
            else
            {
                mapServer.hostname = ipToString(msg.readInt32());
            }
            mapServer.port = msg.readInt16();

            // Prevent the selected local player from being deleted
            player_node = mSelectedCharacter->dummy;
            PlayerInfo::setBackend(mSelectedCharacter->data);

            mSelectedCharacter->dummy = nullptr;

            delete_all(mCharacters);
            mCharacters.clear();
            updateCharSelectDialog();

            if (mNetwork)
                mNetwork->disconnect();
            Client::setState(STATE_CONNECT_GAME);
        }
        break;

        case SMSG_CHANGE_MAP_SERVER:
        {
            GameHandler *gh = static_cast<GameHandler*>(Net::getGameHandler());
            if (!gh || !mNetwork)
                return;
            gh->setMap(msg.readString(16));
            int x = msg.readInt16();
            int y = msg.readInt16();
            mapServer.hostname = ipToString(msg.readInt32());
            mapServer.port = msg.readInt16();

            mNetwork->disconnect();
            Client::setState(STATE_CHANGE_MAP);
            if (player_node)
            {
                player_node->setTileCoords(x, y);
                player_node->setMap(nullptr);
            }
        }
        break;

        default:
            break;
    }
}
Exemple #20
0
void PlayerHandler::processPlayerWarp(Net::MessageIn &msg)
{
    std::string mapPath = msg.readString(16);
    int x = msg.readInt16();
    int y = msg.readInt16();

    logger->log("Warping to %s (%d, %d)", mapPath.c_str(), x, y);

    if (!player_node)
        logger->log1("SMSG_PLAYER_WARP player_node null");

    /*
      * We must clear the local player's target *before* the call
      * to changeMap, as it deletes all beings.
      */
    if (player_node)
        player_node->stopAttack();

    Game *game = Game::instance();

    const std::string &currentMapName = game->getCurrentMapName();
    bool sameMap = (currentMapName == mapPath);

    // Switch the actual map, deleting the previous one if necessary
    mapPath = mapPath.substr(0, mapPath.rfind("."));
    game->changeMap(mapPath);

    int scrollOffsetX = 0;
    int scrollOffsetY = 0;

    if (player_node)
    {
        Map *map = game->getCurrentMap();
        if (map)
        {
            if (x >= map->getWidth())
                x = map->getWidth() - 1;
            if (y >= map->getHeight())
                y = map->getHeight() - 1;
            if (x < 0)
                x = 0;
            if (y < 0)
                y = 0;
            /* Scroll if neccessary */
            if (!sameMap
                || (abs(x - player_node->getTileX())
                > MAP_TELEPORT_SCROLL_DISTANCE)
                || (abs(y - player_node->getTileY())
                > MAP_TELEPORT_SCROLL_DISTANCE))
            {
                scrollOffsetX = (x - player_node->getTileX())
                    * map->getTileWidth();
                scrollOffsetY = (y - player_node->getTileY())
                    * map->getTileHeight();
            }
        }

        player_node->setAction(Being::STAND);
        player_node->setTileCoords(x, y);
        player_node->navigateClean();
    }

    logger->log("Adjust scrolling by %d:%d", scrollOffsetX, scrollOffsetY);

    if (viewport)
    {
        viewport->returnCamera();
        if (miniStatusWindow)
            miniStatusWindow->updateStatus();
        viewport->scrollBy(scrollOffsetX, scrollOffsetY);
    }
}
Exemple #21
0
void LoginHandler::handleMessage(Net::MessageIn &msg)
{
    int code, worldCount;

    switch (msg.getId())
    {
        case SMSG_CHAR_PASSWORD_RESPONSE:
        {
            // 0: acc not found, 1: success, 2: password mismatch, 3: pass too short
            int errMsg = msg.readInt8();
            // Successful pass change
            if (errMsg == 1)
            {
                Client::setState(STATE_CHANGEPASSWORD_SUCCESS);
            }
            // pass change failed
            else
            {
                switch (errMsg)
                {
                    case 0:
                        errorMessage = _("Account was not found. Please re-login.");
                        break;
                    case 2:
                        errorMessage = _("Old password incorrect.");
                        break;
                    case 3:
                        errorMessage = _("New password too short.");
                        break;
                    default:
                        errorMessage = _("Unknown error.");
                        break;
                }
                Client::setState(STATE_ACCOUNTCHANGE_ERROR);
            }
        }
            break;

        case SMSG_UPDATE_HOST:
             int len;

             len = msg.readInt16() - 4;
             mUpdateHost = msg.readString(len);
             loginData.updateHost = mUpdateHost;

             logger->log("Received update host \"%s\" from login server.",
                     mUpdateHost.c_str());
             break;

        case SMSG_LOGIN_DATA:
            // Skip the length word
            msg.skip(2);

            clearWorlds();

            worldCount = (msg.getLength() - 47) / 32;

            mToken.session_ID1 = msg.readInt32();
            mToken.account_ID = msg.readInt32();
            mToken.session_ID2 = msg.readInt32();
            msg.skip(30);                           // unknown
            mToken.sex = msg.readInt8() ? GENDER_MALE : GENDER_FEMALE;

            for (int i = 0; i < worldCount; i++)
            {
                WorldInfo *world = new WorldInfo;

                world->address = msg.readInt32();
                world->port = msg.readInt16();
                world->name = msg.readString(20);
                world->online_users = msg.readInt32();
                world->updateHost = mUpdateHost;
                msg.skip(2);                        // unknown

                logger->log("Network: Server: %s (%s:%d)",
                        world->name.c_str(),
                        ipToString(world->address),
                        world->port);

                mWorlds.push_back(world);
            }
            Client::setState(STATE_WORLD_SELECT);
            break;

        case SMSG_LOGIN_ERROR:
            code = msg.readInt8();
            logger->log("Login::error code: %i", code);

            switch (code)
            {
                case 0:
                    errorMessage = _("Unregistered ID.");
                    break;
                case 1:
                    errorMessage = _("Wrong password.");
                    break;
                case 2:
                    errorMessage = _("Account expired.");
                    break;
                case 3:
                    errorMessage = _("Rejected from server.");
                    break;
                case 4:
                    errorMessage = _("You have been permanently banned from "
                                     "the game. Please contact the GM team.");
                    break;
                case 5:
                    errorMessage = _("Client too old.");
                    break;
                case 6:
                    errorMessage = strprintf(_("You have been temporarily "
                                               "banned from the game until "
                                               "%s.\nPlease contact the GM "
                                               "team via the forums."),
                                               msg.readString(20).c_str());
                    break;
                case 7:
                    errorMessage = _("Server overpopulated.");
                    break;
                case 9:
                    errorMessage = _("This user name is already taken.");
                    break;
                case 99:
                    errorMessage = _("Username permanently erased.");
                    break;
                default:
                    errorMessage = _("Unknown error.");
                    break;
            }
            Client::setState(STATE_ERROR);
            break;

        case SMSG_SERVER_VERSION_RESPONSE:
            {
                // TODO: verify these!

                msg.readInt8(); // -1
                msg.readInt8(); // T
                msg.readInt8(); // M
                msg.readInt8(); // W

                unsigned int options = msg.readInt32();

                mRegistrationEnabled = (options & 1);

                // Leave this last
                mVersionResponse = true;
            }
            break;
    }
}
Exemple #22
0
void PlayerHandler::processPlayerStatUpdate1(Net::MessageIn &msg)
{
    int type = msg.readInt16();
    int value = msg.readInt32();
    if (!player_node)
        return;

    switch (type)
    {
        case 0x0000:
            player_node->setWalkSpeed(Vector(static_cast<float>(
                value), static_cast<float>(value), 0));
            PlayerInfo::setStatBase(WALK_SPEED, value);
            PlayerInfo::setStatMod(WALK_SPEED, 0);
        break;
        case 0x0004: break; // manner
        case 0x0005:
            PlayerInfo::setAttribute(HP, value);
            if (player_node->isInParty() && Party::getParty(1))
            {
                PartyMember *m = Party::getParty(1)
                    ->getMember(player_node->getId());
                if (m)
                {
                    m->setHp(value);
                    m->setMaxHp(PlayerInfo::getAttribute(MAX_HP));
                }
            }
            break;
        case 0x0006:
            PlayerInfo::setAttribute(MAX_HP, value);

            if (player_node->isInParty() && Party::getParty(1))
            {
                PartyMember *m = Party::getParty(1)->getMember(
                    player_node->getId());
                if (m)
                {
                    m->setHp(PlayerInfo::getAttribute(HP));
                    m->setMaxHp(value);
                }
            }
            break;
        case 0x0007:
            PlayerInfo::setAttribute(MP, value);
            break;
        case 0x0008:
            PlayerInfo::setAttribute(MAX_MP, value);
            break;
        case 0x0009:
            PlayerInfo::setAttribute(CHAR_POINTS, value);
            break;
        case 0x000b:
            PlayerInfo::setAttribute(LEVEL, value);
            if (player_node)
            {
                player_node->setLevel(value);
                player_node->updateName();
            }
            break;
        case 0x000c:
            PlayerInfo::setAttribute(SKILL_POINTS, value);
            if (skillDialog)
                skillDialog->update();
            break;
        case 0x0018:
            if (!weightNotice)
            {
                const int max = PlayerInfo::getAttribute(MAX_WEIGHT) / 2;
                const int total = PlayerInfo::getAttribute(TOTAL_WEIGHT);
                if (value >= max && total < max)
                {
                    weightNoticeTime = cur_time + 5;
                    weightNotice = new OkDialog(_("Message"),
                        _("You are carrying more than "
                        "half your weight. You are "
                        "unable to regain health."), DIALOG_OK, false);
                    weightNotice->addActionListener(
                        &weightListener);
                }
                else if (value < max && total >= max)
                {
                    weightNoticeTime = cur_time + 5;
                    weightNotice = new OkDialog(_("Message"),
                        _("You are carrying less than "
                        "half your weight. You "
                        "can regain health."), DIALOG_OK, false);
                    weightNotice->addActionListener(
                        &weightListener);
                }
            }
            PlayerInfo::setAttribute(TOTAL_WEIGHT, value);
            break;
        case 0x0019:
            PlayerInfo::setAttribute(MAX_WEIGHT, value);
            break;

        case 0x0029:
            PlayerInfo::setStatBase(EA_ATK, value);
            PlayerInfo::updateAttrs();
            break;
        case 0x002a:
            PlayerInfo::setStatMod(EA_ATK, value);
            PlayerInfo::updateAttrs();
            break;

        case 0x002b:
            PlayerInfo::setStatBase(EA_MATK, value);
            break;
        case 0x002c:
            PlayerInfo::setStatMod(EA_MATK, value);
            break;

        case 0x002d:
            PlayerInfo::setStatBase(EA_DEF, value);
            break;
        case 0x002e:
            PlayerInfo::setStatMod(EA_DEF, value);
            break;

        case 0x002f:
            PlayerInfo::setStatBase(EA_MDEF, value);
            break;
        case 0x0030:
            PlayerInfo::setStatMod(EA_MDEF, value);
            break;

        case 0x0031:
            PlayerInfo::setStatBase(EA_HIT, value);
            break;

        case 0x0032:
            PlayerInfo::setStatBase(EA_FLEE, value);
            break;
        case 0x0033:
            PlayerInfo::setStatMod(EA_FLEE, value);
            break;

        case 0x0034:
            PlayerInfo::setStatBase(EA_CRIT, value);
            break;

        case 0x0035:
            player_node->setAttackSpeed(value);
            PlayerInfo::setStatBase(ATTACK_DELAY, value);
            PlayerInfo::setStatMod(ATTACK_DELAY, 0);
            PlayerInfo::updateAttrs();
            break;

        case 0x0037:
            PlayerInfo::setStatBase(EA_JOB, value);
            break;

        case 500:
            player_node->setGMLevel(value);
            break;

        default:
            logger->log("QQQQ PLAYER_STAT_UPDATE_1 "
                        + toString(type) + "," + toString(value));
            break;
    }

    if (PlayerInfo::getAttribute(HP) == 0 && !deathNotice)
    {
        deathNotice = new OkDialog(_("Message"),
            randomDeathMessage(), DIALOG_OK, false);
        deathNotice->addActionListener(&deathListener);
        player_node->setAction(Being::DEAD);
    }
}
Exemple #23
0
void CharServerHandler::handleMessage(Net::MessageIn &msg)
{
    switch (msg.getId())
    {
            case SMSG_CHAR_LOGIN:
            {
                msg.skip(2);  // Length word
                msg.skip(20); // Unused

                delete_all(mCharacters);
                mCharacters.clear();

                // Derive number of characters from message length
                const int count = (msg.getLength() - 24) / 106;

                for (int i = 0; i < count; ++i)
                {
                    Net::Character *character = new Net::Character;
                    readPlayerData(msg, character);
                    mCharacters.push_back(character);
                    logger->log("CharServer: Player: %s (%d)",
                                character->dummy->getName().c_str(), character->slot);
                }

                Client::setState(STATE_CHAR_SELECT);
            }
            break;

        case SMSG_CHAR_LOGIN_ERROR:
            switch (msg.readInt8())
            {
                case 0:
                    errorMessage = _("Access denied. Most likely, there are "
                                     "too many players on this server.");
                    break;
                case 1:
                    errorMessage = _("Cannot use this ID.");
                    break;
                default:
                    errorMessage = _("Unknown char-server failure.");
                    break;
            }
            Client::setState(STATE_ERROR);
            break;

        case SMSG_CHAR_CREATE_SUCCEEDED:
            {
                Net::Character *character = new Net::Character;
                readPlayerData(msg, character);
                mCharacters.push_back(character);

                updateCharSelectDialog();

                // Close the character create dialog
                if (mCharCreateDialog)
                {
                    mCharCreateDialog->scheduleDelete();
                    mCharCreateDialog = 0;
                }
            }
            break;

        case SMSG_CHAR_CREATE_FAILED:
            new OkDialog(_("Error"), _("Failed to create character. Most "
                                       "likely the name is already taken."));
            if (mCharCreateDialog)
                mCharCreateDialog->unlock();
            break;

        case SMSG_CHAR_DELETE_SUCCEEDED:
            delete mSelectedCharacter;
            mCharacters.remove(mSelectedCharacter);
            mSelectedCharacter = 0;
            updateCharSelectDialog();
            unlockCharSelectDialog();
            new OkDialog(_("Info"), _("Character deleted."));
            break;

        case SMSG_CHAR_DELETE_FAILED:
            unlockCharSelectDialog();
            new OkDialog(_("Error"), _("Failed to delete character."));
            break;

        case SMSG_CHAR_MAP_INFO:
        {
            msg.skip(4); // CharID, must be the same as local_player->charID
            GameHandler *gh = static_cast<GameHandler*>(Net::getGameHandler());
            gh->setMap(msg.readString(16));
            mapServer.hostname = ipToString(msg.readInt32());
            mapServer.port = msg.readInt16();

            local_player = mSelectedCharacter->dummy;
            PlayerInfo::setBackend(mSelectedCharacter->data);

            // Prevent the selected local player from being deleted
            mSelectedCharacter->dummy = 0;

            delete_all(mCharacters);
            mCharacters.clear();
            updateCharSelectDialog();

            mNetwork->disconnect();
            Client::setState(STATE_CONNECT_GAME);
        }
        break;

        case SMSG_CHANGE_MAP_SERVER:
        {
            GameHandler *gh = static_cast<GameHandler*>(Net::getGameHandler());
            gh->setMap(msg.readString(16));
            int x = msg.readInt16();
            int y = msg.readInt16();
            mapServer.hostname = ipToString(msg.readInt32());
            mapServer.port = msg.readInt16();

            mNetwork->disconnect();
            Client::setState(STATE_CHANGE_MAP);
            Map *map = local_player->getMap();
            const int tileWidth = map->getTileWidth();
            const int tileHeight = map->getTileHeight();
            local_player->setPosition(Vector(x * tileWidth + tileWidth / 2,
                                            y * tileHeight + tileHeight / 2));
            local_player->setMap(0);
        }
        break;
    }
}
void GuildHandler::processGuildMemberList(Net::MessageIn &msg) const
{
    const int length = msg.readInt16();
    if (length < 4)
        return;
    const int count = (length - 4) / 104;
    if (!taGuild)
    {
        logger->log1("!taGuild");
        return;
    }

    taGuild->clearMembers();

    int onlineNum = 0;
    int totalNum = 0;
    for (int i = 0; i < count; i++)
    {
        const int id = msg.readInt32();      // Account ID
        const int charId = msg.readInt32();  // Char ID
        msg.readInt16();                     // Hair
        msg.readInt16();                     // Hair color
        const int gender = msg.readInt16();  // Gender
        const int race = msg.readInt16();    // Class
        const int level = msg.readInt16();   // Level
        const int exp = msg.readInt32();     // Exp
        const int online = msg.readInt32();  // Online
        const int pos = msg.readInt32();     // Position
        msg.skip(50);                        // 0 unused
        std::string name = msg.readString(24);  // Name

        GuildMember *const m = taGuild->addMember(id, charId, name);
        if (m)
        {
            m->setOnline(online);
            m->setID(id);
            m->setCharId(charId);
            m->setGender(Being::intToGender(static_cast<uint8_t>(gender)));
            m->setLevel(level);
            m->setExp(exp);
            m->setPos(pos);
            m->setRace(race);
            if (actorManager)
            {
                Being *const being = actorManager->findBeingByName(
                    name, Being::PLAYER);
                if (being)
                {
                    being->setGuildName(taGuild->getName());
                    if (being->getLevel() != level)
                    {
                        being->setLevel(level);
                        being->updateName();
                    }
                }
            }
            if (online)
                onlineNum ++;
            totalNum ++;
        }
    }
    taGuild->sort();
    if (actorManager)
    {
        actorManager->updatePlayerGuild();
        actorManager->updatePlayerColors();
    }
    if (socialWindow)
        socialWindow->updateGuildCounter(onlineNum, totalNum);
}
Exemple #25
0
void PlayerHandler::handleMessage(Net::MessageIn &msg)
{
    if (!player_node)
        return;

    switch (msg.getId())
    {
        case SMSG_WALK_RESPONSE:
            /*
             * This client assumes that all walk messages succeed,
             * and that the server will send a correction notice
             * otherwise.
             */
            break;

        case SMSG_PLAYER_WARP:
            {
                std::string mapPath = msg.readString(16);
                int x = msg.readInt16();
                int y = msg.readInt16();

                logger->log("Warping to %s (%d, %d)", mapPath.c_str(), x, y);

                /*
                 * We must clear the local player's target *before* the call
                 * to changeMap, as it deletes all beings.
                 */
                player_node->stopAttack();

                Game *game = Game::instance();

                const std::string &currentMapName = game->getCurrentMapName();
                bool sameMap = (currentMapName == mapPath);

                // Switch the actual map, deleting the previous one if necessary
                mapPath = mapPath.substr(0, mapPath.rfind("."));
                game->changeMap(mapPath);

                float scrollOffsetX = 0.0f;
                float scrollOffsetY = 0.0f;

                /* Scroll if necessary */
                Map *map = game->getCurrentMap();
                int tileX = player_node->getTileX();
                int tileY = player_node->getTileY();
                if (!sameMap
                    || (abs(x - tileX) > MAP_TELEPORT_SCROLL_DISTANCE)
                    || (abs(y - tileY) > MAP_TELEPORT_SCROLL_DISTANCE))
                {
                    scrollOffsetX = (x - tileX) * map->getTileWidth();
                    scrollOffsetY = (y - tileY) * map->getTileHeight();
                }

                player_node->setAction(Being::STAND);
                Vector pos = map->getTileCenter(x, y);
                player_node->setPosition(pos);
                // Stop movement
                player_node->setDestination(pos.x, pos.y);

                logger->log("Adjust scrolling by %d:%d", (int) scrollOffsetX,
                           (int) scrollOffsetY);

                viewport->scrollBy(scrollOffsetX, scrollOffsetY);
            }
            break;

        case SMSG_PLAYER_STAT_UPDATE_1:
            {
                if (!player_node)
                    break;
                int type = msg.readInt16();
                int value = msg.readInt32();

                switch (type)
                {
                    case 0x0000:
                      player_node->setMoveSpeed(Vector(value / 10,
                                                       value / 10, 0));
                    break;
                    case 0x0004: break; // manner
                    case 0x0005: PlayerInfo::setAttribute(HP, value); break;
                    case 0x0006: PlayerInfo::setAttribute(MAX_HP, value); break;
                    case 0x0007: PlayerInfo::setAttribute(MP, value); break;
                    case 0x0008: PlayerInfo::setAttribute(MAX_MP, value); break;
                    case 0x0009: PlayerInfo::setAttribute(CHAR_POINTS, value); break;
                    case 0x000b: PlayerInfo::setAttribute(LEVEL, value); break;
                    case 0x000c: PlayerInfo::setAttribute(SKILL_POINTS, value); break;
                    case 0x0018:
                                 if (value >= PlayerInfo::getAttribute(MAX_WEIGHT) / 2 &&
                                         PlayerInfo::getAttribute(TOTAL_WEIGHT) <
                                         PlayerInfo::getAttribute(MAX_WEIGHT) / 2)
                                 {
                                     weightNotice = new OkDialog(_("Message"),
                                             _("You are carrying more than "
                                               "half your weight. You are "
                                               "unable to regain health."));
                                     weightNotice->addActionListener(
                                             &weightListener);
                                 }
                                 PlayerInfo::setAttribute(TOTAL_WEIGHT, value);
                                 break;
                    case 0x0019: PlayerInfo::setAttribute(MAX_WEIGHT, value); break;

                    case 0x0029: PlayerInfo::setStatBase(ATK, value); break;
                    case 0x002a: PlayerInfo::setStatMod(ATK, value); break;

                    case 0x002b: PlayerInfo::setStatBase(MATK, value); break;
                    case 0x002c: PlayerInfo::setStatMod(MATK, value); break;

                    case 0x002d: PlayerInfo::setStatBase(DEF, value); break;
                    case 0x002e: PlayerInfo::setStatMod(DEF, value); break;

                    case 0x002f: PlayerInfo::setStatBase(MDEF, value); break;
                    case 0x0030: PlayerInfo::setStatMod(MDEF, value); break;

                    case 0x0031: PlayerInfo::setStatBase(HIT, value); break;

                    case 0x0032: PlayerInfo::setStatBase(FLEE, value); break;
                    case 0x0033: PlayerInfo::setStatMod(FLEE, value); break;

                    case 0x0034: PlayerInfo::setStatBase(CRIT, value); break;

                    case 0x0035: player_node->setAttackSpeed(value); break;

                    case 0x0037: PlayerInfo::setStatBase(JOB, value); break;

                    case 500: player_node->setGMLevel(value); break;
                }

                if (PlayerInfo::getAttribute(HP) == 0 && !deathNotice)
                {
                    viewport->shakeScreen(100);
                    deathNotice = new OkDialog(_("Message"),
                                               randomDeathMessage(),
                                               false);
                    deathNotice->addActionListener(&deathListener);
                    player_node->setAction(Being::DEAD);
                }
            }

            if (statusWindow)
                statusWindow->updateAttrs();

            break;

        case SMSG_PLAYER_STAT_UPDATE_2:
            switch (msg.readInt16())
            {
                case 0x0001:
                    PlayerInfo::setAttribute(EXP, msg.readInt32());
                    break;
                case 0x0002:
                    PlayerInfo::setStatExperience(JOB, msg.readInt32(),
                                                  PlayerInfo::getStatExperience(JOB).second);
                    break;

                case 0x0014:
                    {
                        int oldMoney = PlayerInfo::getAttribute(MONEY);
                        int newMoney = msg.readInt32();
                        std::string money = Units::formatCurrency(
                                            newMoney - oldMoney);
                        PlayerInfo::setAttribute(MONEY, newMoney);
                        if (newMoney > oldMoney)
                        {
                            if (config.getBoolValue("showpickupchat"))
                                SERVER_NOTICE(strprintf(_("You picked up %s."),
                                            Units::formatCurrency(newMoney -
                                            oldMoney).c_str()))
                            if (config.getBoolValue("showpickupparticle"))
                                player_node->addMessageToQueue(money,
                                                      UserPalette::PICKUP_INFO);
                        }
                    }
                    break;
                case 0x0016:
                    PlayerInfo::setAttribute(EXP_NEEDED, msg.readInt32());
                    break;
                case 0x0017:
                    PlayerInfo::setStatExperience(JOB,
                                                  PlayerInfo::getStatExperience(JOB).first,
                                                  msg.readInt32());
                    break;
            }
            break;

        case SMSG_PLAYER_STAT_UPDATE_3: // Update a base attribute
            {
                int type = msg.readInt32();
                int base = msg.readInt32();
                int bonus = msg.readInt32();

                PlayerInfo::setStatBase(type, base, false);
                PlayerInfo::setStatMod(type, bonus);
            }
            break;

        case SMSG_PLAYER_STAT_UPDATE_4: // Attribute increase ack
            {
                int type = msg.readInt16();
                int ok = msg.readInt8();
                int value = msg.readInt8();

                if (ok != 1)
                {
                    SERVER_NOTICE(_("Cannot raise skill!"))
                }

                PlayerInfo::setStatBase(type, value);
            }
            break;

        // Updates stats and status points
        case SMSG_PLAYER_STAT_UPDATE_5:
            PlayerInfo::setAttribute(CHAR_POINTS, msg.readInt16());

            {
                int val = msg.readInt8();
                PlayerInfo::setStatBase(STR, val);
                if (val >= 99)
                {
                    statusWindow->setPointsNeeded(STR, 0);
                    msg.readInt8();
                }
                else
                {
                    statusWindow->setPointsNeeded(STR, msg.readInt8());
                }

                val = msg.readInt8();
                PlayerInfo::setStatBase(AGI, val);
                if (val >= 99)
                {
                    statusWindow->setPointsNeeded(AGI, 0);
                    msg.readInt8();
                }
                else
                {
                    statusWindow->setPointsNeeded(AGI, msg.readInt8());
                }

                val = msg.readInt8();
                PlayerInfo::setStatBase(VIT, val);
                if (val >= 99)
                {
                    statusWindow->setPointsNeeded(VIT, 0);
                    msg.readInt8();
                }
                else
                {
                    statusWindow->setPointsNeeded(VIT, msg.readInt8());
                }

                val = msg.readInt8();
                PlayerInfo::setStatBase(INT, val);
                if (val >= 99)
                {
                    statusWindow->setPointsNeeded(INT, 0);
                    msg.readInt8();
                }
                else
                {
                    statusWindow->setPointsNeeded(INT, msg.readInt8());
                }

                val = msg.readInt8();
                PlayerInfo::setStatBase(DEX, val);
                if (val >= 99)
                {
                    statusWindow->setPointsNeeded(DEX, 0);
                    msg.readInt8();
                }
                else
                {
                    statusWindow->setPointsNeeded(DEX, msg.readInt8());
                }

                val = msg.readInt8();
                PlayerInfo::setStatBase(LUK, val);
                if (val >= 99)
                {
                    statusWindow->setPointsNeeded(LUK, 0);
                    msg.readInt8();
                }
                else
                {
                    statusWindow->setPointsNeeded(LUK, msg.readInt8());
                }

                PlayerInfo::setStatBase(ATK, msg.readInt16(), false);
                PlayerInfo::setStatMod(ATK, msg.readInt16());

                PlayerInfo::setStatBase(MATK, msg.readInt16(), false);
                PlayerInfo::setStatMod(MATK, msg.readInt16());


                PlayerInfo::setStatBase(DEF, msg.readInt16(), false);
                PlayerInfo::setStatMod(DEF, msg.readInt16());

                PlayerInfo::setStatBase(MDEF, msg.readInt16(), false);
                PlayerInfo::setStatMod(MDEF, msg.readInt16());

                PlayerInfo::setStatBase(HIT, msg.readInt16());

                PlayerInfo::setStatBase(FLEE, msg.readInt16(), false);
                PlayerInfo::setStatMod(FLEE, msg.readInt16());

                PlayerInfo::setStatBase(CRIT, msg.readInt16());
            }

            msg.readInt16();  // manner
            break;

        case SMSG_PLAYER_STAT_UPDATE_6:
            switch (msg.readInt16())
            {
                case 0x0020:
                    statusWindow->setPointsNeeded(STR, msg.readInt8());
                    break;
                case 0x0021:
                    statusWindow->setPointsNeeded(AGI, msg.readInt8());
                    break;
                case 0x0022:
                    statusWindow->setPointsNeeded(VIT, msg.readInt8());
                    break;
                case 0x0023:
                    statusWindow->setPointsNeeded(INT, msg.readInt8());
                    break;
                case 0x0024:
                    statusWindow->setPointsNeeded(DEX, msg.readInt8());
                    break;
                case 0x0025:
                    statusWindow->setPointsNeeded(LUK, msg.readInt8());
                    break;
            }
            break;

        case SMSG_PLAYER_ARROW_MESSAGE:
            {
                int type = msg.readInt16();

                switch (type)
                {
                    case 0:
                        {
                            SERVER_NOTICE(_("Equip arrows first."))
                        }
                        break;
                    default:
                        logger->log("0x013b: Unhandled message %i", type);
                        break;
                }
            }
            break;
    }
}
Exemple #26
0
void AdminRecv::processAccountStats(Net::MessageIn &msg)
{
    UNIMPLEMENTEDPACKET;
    // +++ need show in other players stats window, nick in mStatsName
    msg.readUInt8("str");
    msg.readUInt8("need str");
    msg.readUInt8("agi");
    msg.readUInt8("need agi");
    msg.readUInt8("vit");
    msg.readUInt8("need vit");
    msg.readUInt8("int");
    msg.readUInt8("need int");
    msg.readUInt8("dex");
    msg.readUInt8("need dex");
    msg.readUInt8("luk");
    msg.readUInt8("need luk");
    msg.readInt16("attack");
    msg.readInt16("refine");
    msg.readInt16("matk max");
    msg.readInt16("matk min");
    msg.readInt16("item def");
    msg.readInt16("plus def");
    msg.readInt16("mdef");
    msg.readInt16("plus mdef");
    msg.readInt16("hit");
    msg.readInt16("flee");
    msg.readInt16("flee2/10");
    msg.readInt16("cri/10");
    msg.readInt16("speed");
    msg.readInt16("zero");
}
Exemple #27
0
void GuildHandler::processGuildMemberList(Net::MessageIn &msg)
{
    const int length = msg.readInt16("len");
    if (length < 4)
        return;
    const int count = (length - 4) / 104;
    if (!taGuild)
    {
        logger->log1("!taGuild");
        return;
    }

    taGuild->clearMembers();

    int onlineNum = 0;
    int totalNum = 0;
    for (int i = 0; i < count; i++)
    {
        const BeingId id = msg.readBeingId("account id");
        const int charId = msg.readInt32("char id");
        msg.readInt16("hair");
        msg.readInt16("hair color");
        const int gender = msg.readInt16("gender");
        const int race = msg.readInt16("class");
        const int level = msg.readInt16("level");
        const int exp = msg.readInt32("exp");
        const int online = msg.readInt32("online");
        const int pos = msg.readInt32("position");
        msg.skip(50, "unused");
        std::string name = msg.readString(24, "name");

        GuildMember *const m = taGuild->addMember(id, charId, name);
        if (m)
        {
            m->setOnline(online);
            m->setID(id);
            m->setCharId(charId);
            m->setGender(Being::intToGender(static_cast<uint8_t>(gender)));
            m->setLevel(level);
            m->setExp(exp);
            m->setPos(pos);
            m->setRace(race);
            if (actorManager)
            {
                Being *const being = actorManager->findBeingByName(
                    name, ActorType::Player);
                if (being)
                {
                    being->setGuildName(taGuild->getName());
                    if (being->getLevel() != level)
                    {
                        being->setLevel(level);
                        being->updateName();
                    }
                }
            }
            if (online)
                onlineNum ++;
            totalNum ++;
        }
    }
    taGuild->sort();
    if (actorManager)
    {
        actorManager->updatePlayerGuild();
        actorManager->updatePlayerColors();
    }
    if (socialWindow)
        socialWindow->updateGuildCounter(onlineNum, totalNum);
}
Exemple #28
0
void SkillRecv::processSkillFailed(Net::MessageIn &msg)
{
    // Action failed (ex. sit because you have not reached the
    // right level)
    const int skillId = msg.readInt16("skill id");
    const int bskill  = msg.readInt32("btype");
    const signed char success = msg.readUInt8("success");
    const signed char reason  = msg.readUInt8("reason");
    if (success != CAST_S32(SKILL_FAILED)
        && bskill == CAST_S32(BSKILL_EMOTE))
    {
        logger->log("Action: %d/%d", bskill, success);
    }

    if (localPlayer)
        localPlayer->stopCast(true);
    std::string txt;
    if (success == CAST_S32(SKILL_FAILED) && bskill != 0)
    {
        if (localPlayer && bskill == CAST_S32(BSKILL_EMOTE)
            && reason == CAST_S32(RFAIL_SKILLDEP))
        {
            localPlayer->stopAdvert();
        }

        const SkillInfo *const info = skillDialog->getSkill(bskill);
        if (info)
        {
            txt = info->errorText;
        }
        else
        {
            // TRANSLATORS: skill error message
            txt = strprintf(_("Unknown skill error: %d"), bskill);
        }
    }
    else
    {
        const SkillInfo *const info = skillDialog->getSkill(skillId);
        if (info)
        {
            txt = info->errorText + ".";
        }
        else
        {
            // TRANSLATORS: skill error message
            txt = strprintf(_("Unknown skill error: %d."), skillId);
        }
    }

    txt.append(" ");
    switch (reason)
    {
        case RFAIL_SKILLDEP:
            // TRANSLATORS: error message
            txt.append(_("You have not yet reached a high enough lvl!"));
            break;
        case RFAIL_INSUFHP:
            // TRANSLATORS: error message
            txt.append(_("Insufficient HP!"));
            break;
        case RFAIL_INSUFSP:
            // TRANSLATORS: error message
            txt.append(_("Insufficient SP!"));
            break;
        case RFAIL_NOMEMO:
            // TRANSLATORS: error message
            txt.append(_("You have no memos!"));
            break;
        case RFAIL_SKILLDELAY:
            // TRANSLATORS: error message
            txt.append(_("You cannot do that right now!"));
            break;
        case RFAIL_ZENY:
            // TRANSLATORS: error message
            txt.append(_("Seems you need more money... ;-)"));
            break;
        case RFAIL_WEAPON:
            // TRANSLATORS: error message
            txt.append(_("You cannot use this skill with that "
                "kind of weapon!"));
            break;
        case RFAIL_REDGEM:
            // TRANSLATORS: error message
            txt.append(_("You need another red gem!"));
            break;
        case RFAIL_BLUEGEM:
            // TRANSLATORS: error message
            txt.append(_("You need another blue gem!"));
            break;
        case RFAIL_OVERWEIGHT:
            // TRANSLATORS: error message
            txt.append(_("You're carrying to much to do this!"));
            break;
        case RFAIL_SUMMON:
            // TRANSLATORS: error message
            txt.append(_("Fail summon."));
            break;
        case RFAIL_SPIRITS:
            // TRANSLATORS: error message
            txt.append(_("Need spirits."));
            break;
        case RFAIL_NEED_EQUIPMENT:
        {
            const int itemId = bskill >> 16U;
            const int amount = bskill & 0xFFFFU;
            const ItemInfo &info = ItemDB::get(itemId);
            if (amount == 1)
            {
                // TRANSLATORS: skill error message
                txt.append(strprintf(_("Need equipment %s."),
                    info.getLink().c_str()));
            }
            else
            {
                // TRANSLATORS: skill error message
                txt.append(strprintf(_("Need equipment %s and amount %d"),
                    info.getLink().c_str(),
                    amount));
            }
            break;
        }
        case RFAIL_NEED_ITEM:
        {
            const int itemId = bskill >> 16U;
            const int amount = bskill & 0xFFFFU;
            const ItemInfo &info = ItemDB::get(itemId);
            if (amount == 1)
            {
                // TRANSLATORS: skill error message
                txt.append(strprintf(_("Need item %s."),
                    info.getLink().c_str()));
            }
            else
            {
                // TRANSLATORS: skill error message
                txt.append(strprintf(_("Need item %s and amount %d"),
                    info.getLink().c_str(),
                    amount));
            }
            break;
        }
        case RFAIL:
        {
            // TRANSLATORS: error message
            txt.append(_("Skill failed!"));
            break;
        }

        default:
            UNIMPLEMENTEDPACKETFIELD(reason);
            break;
    }

    NotifyManager::notify(NotifyTypes::SKILL_FAIL_MESSAGE, txt);
}
Exemple #29
0
void PartyHandler::processPartyInfo(Net::MessageIn &msg)
{
    bool oldParty = false;
    std::set<std::string> names;
    if (!Ea::taParty)
    {
        logger->log1("error: party empty in SMSG_PARTY_INFO");
        Ea::taParty = Party::getParty(1);
    }
    if (Ea::taParty)
    {
        if (Ea::taParty->getNumberOfElements() > 1)
        {
            oldParty = true;

            Ea::taParty->getNamesSet(names);
        }
    }

    if (!player_node)
        logger->log1("error: player_node==0 in SMSG_PARTY_INFO");

    if (Ea::taParty)
        Ea::taParty->clearMembers();

    int length = msg.readInt16();
    if (Ea::taParty)
        Ea::taParty->setName(msg.readString(24));

    int count = (length - 28) / 46;
    if (player_node && Ea::taParty)
    {
        player_node->setParty(Ea::taParty);
        player_node->setPartyName(Ea::taParty->getName());
    }

    for (int i = 0; i < count; i++)
    {
        int id = msg.readInt32();
        std::string nick = msg.readString(24);
        std::string map = msg.readString(16);
        bool leader = msg.readInt8() == 0;
        bool online = msg.readInt8() == 0;

        if (Ea::taParty)
        {
            PartyMember *member = nullptr;
            if (oldParty)
            {
                //member = Ea::taParty->getMember(id);
                if (Ea::partyTab && names.find(nick) == names.end())
                {
                    Ea::partyTab->chatLog(strprintf(
                        _("%s has joined your party."),
                        nick.c_str()), BY_SERVER);
                }
            }
            member = Ea::taParty->addMember(id, nick);

            if (member)
            {
                member->setLeader(leader);
                member->setOnline(online);
                member->setMap(map);
            }
        }
    }

    if (Ea::taParty)
        Ea::taParty->sort();

    if (player_node && Ea::taParty)
    {
        player_node->setParty(Ea::taParty);
        player_node->setPartyName(Ea::taParty->getName());
    }
}
void SkillHandler::processSkillFailed(Net::MessageIn &msg) const
{
    // Action failed (ex. sit because you have not reached the
    // right level)
    const int skillId   = msg.readInt16();
    const int16_t bskill  = msg.readInt16();
    msg.readInt16();  // btype
    const signed char success = msg.readInt8();
    const signed char reason  = msg.readInt8();
    if (success != static_cast<int>(SKILL_FAILED)
        && bskill == static_cast<int>(BSKILL_EMOTE))
    {
        logger->log("Action: %d/%d", bskill, success);
    }

    std::string txt;
    if (success == static_cast<int>(SKILL_FAILED)
        && skillId == static_cast<int>(SKILL_BASIC))
    {
        if (player_node && bskill == static_cast<int>(BSKILL_EMOTE)
            && reason == static_cast<int>(RFAIL_SKILLDEP))
        {
            player_node->stopAdvert();
        }

        switch (bskill)
        {
            case BSKILL_TRADE:
                // TRANSLATORS: error message
                txt = _("Trade failed!");
                break;
            case BSKILL_EMOTE:
                // TRANSLATORS: error message
                txt = _("Emote failed!");
                break;
            case BSKILL_SIT:
                // TRANSLATORS: error message
                txt = _("Sit failed!");
                break;
            case BSKILL_CREATECHAT:
                // TRANSLATORS: error message
                txt = _("Chat creating failed!");
                break;
            case BSKILL_JOINPARTY:
                // TRANSLATORS: error message
                txt = _("Could not join party!");
                break;
            case BSKILL_SHOUT:
                // TRANSLATORS: error message
                txt = _("Cannot shout!");
                break;
            default:
                logger->log("QQQ SMSG_SKILL_FAILED: bskill "
                            + toString(bskill));
                break;
        }

        txt.append(" ");

        switch (reason)
        {
            case RFAIL_SKILLDEP:
                // TRANSLATORS: error message
                txt.append(_("You have not yet reached a high enough lvl!"));
                break;
            case RFAIL_INSUFHP:
                // TRANSLATORS: error message
                txt.append(_("Insufficient HP!"));
                break;
            case RFAIL_INSUFSP:
                // TRANSLATORS: error message
                txt.append(_("Insufficient SP!"));
                break;
            case RFAIL_NOMEMO:
                // TRANSLATORS: error message
                txt.append(_("You have no memos!"));
                break;
            case RFAIL_SKILLDELAY:
                // TRANSLATORS: error message
                txt.append(_("You cannot do that right now!"));
                break;
            case RFAIL_ZENY:
                // TRANSLATORS: error message
                txt.append(_("Seems you need more money... ;-)"));
                break;
            case RFAIL_WEAPON:
                // TRANSLATORS: error message
                txt.append(_("You cannot use this skill with that "
                    "kind of weapon!"));
                break;
            case RFAIL_REDGEM:
                // TRANSLATORS: error message
                txt.append(_("You need another red gem!"));
                break;
            case RFAIL_BLUEGEM:
                // TRANSLATORS: error message
                txt.append(_("You need another blue gem!"));
                break;
            case RFAIL_OVERWEIGHT:
                // TRANSLATORS: error message
                txt.append(_("You're carrying to much to do this!"));
                break;
            default:
                // TRANSLATORS: error message
                txt.append(_("Huh? What's that?"));
                logger->log("QQQ SMSG_SKILL_FAILED: reason "
                            + toString(reason));
                break;
        }
    }
    else
    {
        switch (skillId)
        {
            case SKILL_WARP :
                // TRANSLATORS: error message
                txt = _("Warp failed...");
                break;
            case SKILL_STEAL :
                // TRANSLATORS: error message
                txt = _("Could not steal anything...");
                break;
            case SKILL_ENVENOM :
                // TRANSLATORS: error message
                txt = _("Poison had no effect...");
                break;
            default:
                logger->log("QQQ SMSG_SKILL_FAILED: skillId "
                            + toString(skillId));
                break;
        }
    }

    NotifyManager::notify(NotifyManager::SKILL_FAIL_MESSAGE, txt);
}