Exemple #1
0
void BeingHandler::handleBeingsDamageMessage(Net::MessageIn &msg)
{
    while (msg.getUnreadLength())
    {
        Being *being = actorSpriteManager->findBeing(msg.readInt16());
        int damage = msg.readInt16();
        if (being)
        {
            being->takeDamage(0, damage, Being::HIT);
        }
    }
}
Exemple #2
0
void MapComposite::update()
{
    // Update object status
    const std::vector< Entity * > &entities = getEverything();
    for (std::vector< Entity * >::const_iterator it = entities.begin(),
         it_end = entities.end(); it != it_end; ++it)
    {
        (*it)->update();
    }

    if (mUpdateCallback.isValid())
    {
        Script *s = ScriptManager::currentState();
        s->setMap(this);
        s->prepare(mUpdateCallback);
        s->push(mID);
        s->execute();
    }

    // Move objects around and update zones.
    for (BeingIterator it(getWholeMapIterator()); it; ++it)
    {
        (*it)->move();
    }

    for (int i = 0; i < mContent->mapHeight * mContent->mapWidth; ++i)
    {
        mContent->zones[i].destinations.clear();
    }

    // Cannot use a WholeMap iterator as objects will change zones under its feet.
    for (std::vector< Entity * >::iterator i = mContent->entities.begin(),
         i_end = mContent->entities.end(); i != i_end; ++i)
    {
        if (!(*i)->canMove())
            continue;

        Being *obj = static_cast< Being * >(*i);

        const Point &pos1 = obj->getOldPosition(),
                    &pos2 = obj->getPosition();

        MapZone &src = mContent->getZone(pos1),
                &dst = mContent->getZone(pos2);
        if (&src != &dst)
        {
            addZone(src.destinations, &dst - mContent->zones);
            src.remove(obj);
            dst.insert(obj);
        }
    }
}
Exemple #3
0
void GameHandler::handleAttack(GameClient &client, MessageIn &message)
{
    int id = message.readInt16();
    LOG_DEBUG("Character " << client.character->getPublicID()
              << " attacked being " << id);

    Being *being = findBeingNear(client.character, id);
    if (being && being->getType() != OBJECT_NPC)
    {
        client.character->setTarget(being);
        client.character->setAction(ATTACK);
    }
}
Exemple #4
0
void Monster::forgetTarget(Entity *t)
{
    Being *b = static_cast< Being * >(t);
    mAnger.erase(b);
    b->removeListener(&mTargetListener);

    if (b->getType() == OBJECT_CHARACTER)
    {
        Character *c = static_cast< Character * >(b);
        mExpReceivers.erase(c);
        mLegalExpReceivers.erase(c);
    }
}
Exemple #5
0
void BeingHandler::handleBeingLooksChangeMessage(Net::MessageIn &msg)
{
    Being *being = actorSpriteManager->findBeing(msg.readInt16());
    if (!being || being->getType() != ActorSprite::PLAYER)
        return;
    handleLooks(being, msg);
    if (msg.getUnreadLength())
    {
        int style = msg.readInt16();
        int color = msg.readInt16();
        being->setSprite(SPRITE_HAIR, style * -1, ColorDB::get(color));
    }
}
Exemple #6
0
void BeingHandler::handleBeingAttackMessage(Net::MessageIn &msg)
{
    Being *being = actorSpriteManager->findBeing(msg.readInt16());
    const BeingDirection direction = (BeingDirection) msg.readInt8();
    const int attackType = msg.readInt8();

    if (!being)
        return;

    being->setDirection(direction);

    being->setAction(Being::ATTACK, attackType);
}
Exemple #7
0
Being *BeingManager::findBeingByName(const std::string &name,
                                     Being::Type type) const
{
    for (Beings::const_iterator i = mBeings.begin(), i_end = mBeings.end();
         i != i_end; ++i)
    {
        Being *being = (*i);
        if (being->getName() == name &&
           (type == Being::UNKNOWN || type == being->getType()))
            return being;
    }
    return NULL;
}
Exemple #8
0
void DebugWindow::draw(gcn::Graphics *g)
{
    Window::draw(g);

    if (player_node)
    {
        Being *target = player_node->getTarget();
        if (target)
        {
            Graphics *g2 = static_cast<Graphics*>(g);
            target->draw(g2, -target->getPixelX() + 16 + getWidth() / 2,
                         -target->getPixelY() + 32 + getHeight() / 2);
        }
    }
}
Exemple #9
0
static Being *findBeingNear(Actor *p, int id)
{
    MapComposite *map = p->getMap();
    const Point &ppos = p->getPosition();
    // See map.h for tiles constants
    const int pixelDist = DEFAULT_TILE_LENGTH * TILES_TO_BE_NEAR;
    for (BeingIterator i(map->getAroundPointIterator(ppos, pixelDist)); i; ++i)
    {
        Being *b = *i;
        if (b->getPublicID() != id)
            continue;
        return ppos.inRangeOf(b->getPosition(), pixelDist) ? b : 0;
    }
    return 0;
}
Exemple #10
0
Command Interface::detailspage(Being & b) {
    Command c;
    bool viewingplayer = false;

    do {
        Being & viewed = (viewingplayer ? GAME.being[0] : b);
        displaydetails(viewed);
        if (viewed.isplayer) {
            if (b.isplayer)
                msg("Viewing your system details. Press any key...");
            else {
                char msgbuf[128];

                strcpy(msgbuf, "\
Viewing your system details. Press d to view ");
                strcat(msgbuf, b.getname());
                strcat(msgbuf, "'s systems.");
                msg(msgbuf);
            }
        }
        else {
            char msgbuf[128];

            strcpy(msgbuf, "Viewing ");
            strcat(msgbuf, viewed.getname());
            strcat(msgbuf, "'s system details. Press d to view your systems.");
            msg(msgbuf);
        }
        c = getcommand();
        if (c == COMMAND_DETAILS)
            if (b.isplayer)
                c = COMMAND_UNDEFINED;
            else
                viewingplayer = !viewingplayer;
    } while (c == COMMAND_DETAILS);
Exemple #11
0
void BuySellHandler::handleMessage(Net::MessageIn &msg)
{
    Being *being = actorSpriteManager->findBeing(msg.readInt16());
    if (!being || being->getType() != ActorSprite::NPC)
    {
        return;
    }

    int npcId = being->getId();

    switch (msg.getId())
    {
        case GPMSG_NPC_BUY:
        {
            BuyDialog* dialog = new BuyDialog(npcId);

            dialog->reset();
            dialog->setMoney(PlayerInfo::getAttribute(MONEY));

            while (msg.getUnreadLength())
            {
                int itemId = msg.readInt16();
                int amount = msg.readInt16();
                int value = msg.readInt16();
                dialog->addItem(itemId, amount, value);
            }
            break;
        }

        case GPMSG_NPC_SELL:
        {
            SellDialog* dialog = new SellDialog(npcId);

            dialog->reset();
            dialog->setMoney(PlayerInfo::getAttribute(MONEY));

            while (msg.getUnreadLength())
            {
                int itemId = msg.readInt16();
                int amount = msg.readInt16();
                int value = msg.readInt16();
                dialog->addItem(new Item(itemId, amount, false), value);
            }
            break;
        }
    }
}
Exemple #12
0
void Monster::changeAnger(Actor *target, int amount)
{
    if (target && (target->getType() == OBJECT_MONSTER
        || target->getType() == OBJECT_CHARACTER))
    {
        Being *t = static_cast< Being * >(target);
        if (mAnger.find(t) != mAnger.end())
        {
            mAnger[t] += amount;
        }
        else
        {
            mAnger[t] = amount;
            t->addListener(&mTargetListener);
        }
    }
}
Exemple #13
0
void Being::showName()
{
    delete mDispName;
    mDispName = 0;
    std::string mDisplayName(mName);

    Being* player =  static_cast<Being*>(this);
    if (player)
    {
        if (config.getBoolValue("showgender"))
        {
            if (getGender() == GENDER_FEMALE)
                mDisplayName += " \u2640";
            else if (getGender() == GENDER_MALE)
                mDisplayName += " \u2642";
        }

        // Display the IP when under tmw-Athena (GM only).
        if (Net::getNetworkType() == ServerInfo::TMWATHENA && local_player
        && local_player->getShowIp() && player->getIp())
        {
            mDisplayName += strprintf(" %s", ipToString(player->getIp()));
        }
    }

    if (getType() == MONSTER)
    {
        if (config.getBoolValue("showMonstersTakedDamage"))
        {
            mDisplayName += ", " + toString(getDamageTaken());
        }
    }

    gcn::Font *font = 0;
    if (local_player && local_player->getTarget() == this
        && getType() != MONSTER)
    {
        font = boldFont;
    }

    mDispName = new FlashText(mDisplayName, getPixelX(), getPixelY(),
                              gcn::Graphics::CENTER, mNameColor, font);

    updateCoords();
}
Exemple #14
0
static void spawn(Character *from, MonsterClass *specy, int nb)
{
    MapComposite *map = from->getMap();
    const Point &pos = from->getPosition();

    for (int i = 0; i < nb; ++i)
    {
        Being *monster = new Monster(specy);
        monster->setMap(map);
        monster->setPosition(pos);
        monster->clearDestination();
        if (!GameState::insertSafe(monster))
        {
            // The map is full. Break out.
            break;
        }
    }
}
Exemple #15
0
void BeingManager::getPlayerNames(std::vector<std::string> &names,
                                  bool npcNames)
{
    Beings::iterator i = mBeings.begin();
    names.clear();

    while (i != mBeings.end())
    {
        Being *being = (*i);
        if ((being->getType() == Being::PLAYER
             || (being->getType() == Being::NPC && npcNames))
            && being->getName() != "")
        {
            names.push_back(being->getName());
        }
        ++i;
    }
}
Exemple #16
0
        bool operator() (ActorSprite *actor)
        {
            if (actor->getType() == ActorSprite::FLOOR_ITEM)
                return false;
            Game *game = Game::instance();
            if (!game)
                return false;

            Being* b = static_cast<Being*>(actor);

            uint16_t other_y = y + ((b->getType() == ActorSprite::NPC) ? 1 : 0);
            const Vector &pos = b->getPosition();
            return ((int) pos.x / game->getCurrentTileWidth() == x &&
                    ((int) pos.y / game->getCurrentTileHeight() == y
                    || (int) pos.y / game->getCurrentTileHeight() == other_y) &&
                    b->isAlive() &&
                    (type == ActorSprite::UNKNOWN || b->getType() == type));
        }
Exemple #17
0
void BeingManager::logic()
{
    Beings::iterator i = mBeings.begin();
    while (i != mBeings.end())
    {
        Being *being = (*i);

        being->logic();

        if (being->mAction == Being::DEAD && being->mFrame >= 20)
        {
            destroy(being);
            i = mBeings.erase(i);
        }
        else
            ++i;
    }
}
Exemple #18
0
static Being *findBeing(const std::string &name, const bool npc)
{
    if (!localPlayer || !actorManager)
        return nullptr;

    Being *being = nullptr;

    if (name.empty())
    {
        being = localPlayer->getTarget();
    }
    else
    {
        being = actorManager->findBeingByName(
            name, ActorType::Unknown);
    }
    if (!being && npc)
    {
        being = actorManager->findNearestLivingBeing(
            localPlayer, 1, ActorType::Npc, AllowSort_true);
        if (being)
        {
            if (abs(being->getTileX() - localPlayer->getTileX()) > 1
                || abs(being->getTileY() - localPlayer->getTileY()) > 1)
            {
                being = nullptr;
            }
        }
    }
    if (!being && npc)
    {
        being = actorManager->findNearestLivingBeing(
            localPlayer, 1, ActorType::Player, AllowSort_true);
        if (being)
        {
            if (abs(being->getTileX() - localPlayer->getTileX()) > 1
                || abs(being->getTileY() - localPlayer->getTileY()) > 1)
            {
                being = nullptr;
            }
        }
    }
    return being;
}
Exemple #19
0
void PartyHandler::processPartyLeave(Net::MessageIn &msg)
{
    int id = msg.readInt32();
    std::string nick = msg.readString(24);
    msg.readInt8();     // fail
    if (!player_node)
        return;

    if (id == player_node->getId())
    {
        if (Ea::taParty)
        {
            Ea::taParty->removeFromMembers();
            Ea::taParty->clearMembers();
        }
        SERVER_NOTICE(_("You have left the party."))
        delete Ea::partyTab;
        Ea::partyTab = nullptr;

        if (socialWindow && Ea::taParty)
            socialWindow->removeTab(Ea::taParty);
        player_node->setPartyName("");
    }
    else
    {
        if (Ea::partyTab)
        {
            Ea::partyTab->chatLog(strprintf(
                _("%s has left your party."),
                nick.c_str()), BY_SERVER);
        }
        if (actorSpriteManager)
        {
            Being *b = actorSpriteManager->findBeing(id);
            if (b && b->getType() == Being::PLAYER)
            {
                b->setParty(nullptr);
                b->setPartyName("");
            }
        }
        if (Ea::taParty)
            Ea::taParty->removeMember(id);
    }
}
Exemple #20
0
void PartyHandler::processPartyInvited(Net::MessageIn &msg)
{
    int id = msg.readInt32();
    std::string partyName = msg.readString(24);
    std::string nick("");
    Being *being;

    if (actorSpriteManager)
    {
        if ((being = actorSpriteManager->findBeing(id)))
        {
            if (being && being->getType() == Being::PLAYER)
                nick = being->getName();
        }
    }

    if (socialWindow)
        socialWindow->showPartyInvite(partyName, nick);
}
void BuySellHandler::handleMessage(MessageIn &msg)
{
    Being *being = beingManager->findBeing(msg.readInt16());
    if (!being || being->getType() != Being::NPC)
    {
        return;
    }

    current_npc = being->getId();

    switch (msg.getId())
    {
        case GPMSG_NPC_BUY:
            buyDialog->reset();
            buyDialog->setMoney(player_node->getMoney());
            buyDialog->setVisible(true);

            while (msg.getUnreadLength())
            {
                int itemId = msg.readInt16();
                int amount = msg.readInt16();
                int value = msg.readInt16();
                buyDialog->addItem(itemId, amount, value);
            }
            break;

        case GPMSG_NPC_SELL:
            sellDialog->setMoney(player_node->getMoney());
            sellDialog->reset();
            sellDialog->setVisible(true);

            while (msg.getUnreadLength())
            {
                int itemId = msg.readInt16();
                int amount = msg.readInt16();
                int value = msg.readInt16();
                sellDialog->addItem(new Item(itemId, amount, false), value);
            }
            break;
    }
}
Exemple #22
0
Being *BeingManager::findBeingByPixel(int x, int y) const
{
    Beings::const_iterator itr = mBeings.begin();
    Beings::const_iterator itr_end = mBeings.end();

    for (; itr != itr_end; ++itr)
    {
        Being *being = (*itr);

        int xtol = being->getWidth() / 2;
        int uptol = being->getHeight();

        if ((being->isAlive()) &&
            (being != player_node) &&
            (being->getPixelX() - xtol <= x) &&
            (being->getPixelX() + xtol >= x) &&
            (being->getPixelY() - uptol <= y) &&
            (being->getPixelY() >= y))
        {
            return being;
        }
    }

    return NULL;
}
Exemple #23
0
void BeingManager::logic()
{
    Beings::iterator i = mBeings.begin();
    while (i != mBeings.end())
    {
        Being *being = (*i);

        being->logic();

        if (!being->isAlive() &&
            Net::getGameHandler()->removeDeadBeings() &&
            being->getCurrentFrame() >= 20)
        {
            delete being;
            i = mBeings.erase(i);
        }
        else
        {
            ++i;
        }
    }
}
Exemple #24
0
void BeingHandler::handleBeingActionChangeMessage(Net::MessageIn &msg)
{
    Being *being = actorSpriteManager->findBeing(msg.readInt16());
    Being::Action action = (Being::Action) msg.readInt8();
    if (!being)
        return;

    being->setAction(action);

    if (action == Being::DEAD && being == player_node)
    {
        static char const *const deadMsg[] =
        {
            _("You are dead."),
            _("We regret to inform you that your character was killed in "
              "battle."),
            _("You are not that alive anymore."),
            _("The cold hands of the grim reaper are grabbing for your soul."),
            _("Game Over!"),
            _("No, kids. Your character did not really die. It... err... "
              "went to a better place."),
            _("Your plan of breaking your enemies weapon by bashing it with "
              "your throat failed."),
            _("I guess this did not run too well."),
            _("Do you want your possessions identified?"), // Nethack reference
            _("Sadly, no trace of you was ever found..."), // Secret of Mana reference
            _("Annihilated."), // Final Fantasy VI reference
            _("Looks like you got your head handed to you."), // Earthbound reference
            _("You screwed up again, dump your body down the tubes and get "
              "you another one.") // Leisure Suit Larry 1 Reference

        };
        std::string message(deadMsg[rand()%13]);
        message.append(std::string(" ") + _("Press OK to respawn."));
        OkDialog *dlg = new OkDialog(_("You Died"), message, false);
        dlg->addActionListener(&(ManaServ::respawnListener));
    }
}
void ChatHandler::handleGameChatMessage(Net::MessageIn &msg)
{
    short id = msg.readInt16();
    std::string chatMsg = msg.readString();

    if (id == 0)
    {
        localChatTab->chatLog(chatMsg, BY_SERVER);
        return;
    }

    Being *being = beingManager->findBeing(id);

    std::string mes;
    if (being)
    {
        mes = being->getName() + " : " + chatMsg;
        being->setSpeech(chatMsg, SPEECH_TIME);
    }
    else
        mes = "Unknown : " + chatMsg;

    localChatTab->chatLog(mes, being == player_node ? BY_PLAYER : BY_OTHER);
}
Exemple #26
0
int Interface::selectitem(char * question, Being & viewed) {
    int ret;
    bool done = false;
    bool readcommand = true;
    Command c;

    while (!done) {
        if (readcommand) {
            query(question);
            c = getcommand();
        }
        else
            readcommand = true;
        switch (c) {
        case COMMAND_CANCEL:
            ret = -1; done = true; break;
        case COMMAND_1:
            ret = 0; done = true; break;
        case COMMAND_2:
            ret = 1; done = true; break;
        case COMMAND_3:
            ret = 2; done = true; break;
        case COMMAND_4:
            ret = 3; done = true; break;
        case COMMAND_5:
            ret = 4; done = true; break;
        case COMMAND_6:
            ret = 5; done = true; break;
        case COMMAND_7:
            ret = 6; done = true; break;
        case COMMAND_8:
            ret = 7; done = true; break;
        case COMMAND_DETAILS:
            c = detailspage(viewed);
            GAME.normaldisplay();
            viewed.displaystatus();
            readcommand = false;
            break;;
        default:
            break;
        }
    }

    return ret;
}
Exemple #27
0
void GraphicsMap::Draw()
{
	ScreenGame->clear();
	// First draw the map objects onto the graphical map
	for (int x = 0; x < MapWidth; x++)
		for (int y = 0; y < MapHeight; y++)
			{
				if (FOVMap.map[x][y])
					DrawDisplayTile(x, y, ToDraw->GetMapCell(x,y)->GetTile(), ScreenGame);
				else
					DrawDisplayTile(x, y, DisplayTile(' ', TCODColor::black, TCODColor::black), ScreenGame);
			}

	// Draw the items to the graphical map
	for (unsigned int i = 0; i < (ToDraw->Items.size()); i++)
	{
		// Get the item from the map
		Item* itm = ToDraw->Items[i];
		// If it's in the FOV, draw it
		if (FOVMap.map[itm->GetX()][itm->GetY()])
			DrawDisplayTile(itm->GetX(), itm->GetY(), itm->GetTile(), ScreenGame);
		else
			DrawDisplayTile(itm->GetX(), itm->GetY(), DisplayTile(' ', TCODColor::black, TCODColor::black), ScreenGame);
	}
	
	// Draw the beings to the graphical map
	for (unsigned int i = 0; i < (ToDraw->Beings.size()); i++)
	{
		// Get the being from the map
		Being* b = ToDraw->Beings[i];
		if (FOVMap.map[b->GetX()][b->GetY()])
			DrawDisplayTile(b->GetX(), b->GetY(), b->GetTile(), ScreenGame);
		else
			DrawDisplayTile(b->GetX(), b->GetY(), DisplayTile(' ', TCODColor::black, TCODColor::black), ScreenGame);
	}
}
Exemple #28
0
/**
 * Informs a player of what happened around the character.
 */
static void informPlayer(MapComposite *map, Character *p)
{
    MessageOut moveMsg(GPMSG_BEINGS_MOVE);
    MessageOut damageMsg(GPMSG_BEINGS_DAMAGE);
    const Point &pold = p->getOldPosition(), ppos = p->getPosition();
    int pid = p->getPublicID(), pflags = p->getUpdateFlags();
    int visualRange = Configuration::getValue("game_visualRange", 448);

    // Inform client about activities of other beings near its character
    for (BeingIterator it(map->getAroundBeingIterator(p, visualRange));
         it; ++it)
    {
        Being *o = *it;

        const Point &oold = o->getOldPosition(), opos = o->getPosition();
        int otype = o->getType();
        int oid = o->getPublicID(), oflags = o->getUpdateFlags();
        int flags = 0;

        // Check if the character p and the moving object o are around.
        bool wereInRange = pold.inRangeOf(oold, visualRange) &&
                           !((pflags | oflags) & UPDATEFLAG_NEW_ON_MAP);
        bool willBeInRange = ppos.inRangeOf(opos, visualRange);

        if (!wereInRange && !willBeInRange)
        {
            // Nothing to report: o and p are far away from each other.
            continue;
        }


        if (wereInRange && willBeInRange)
        {
            // Send attack messages.
            if ((oflags & UPDATEFLAG_ATTACK) && oid != pid)
            {
                MessageOut AttackMsg(GPMSG_BEING_ATTACK);
                AttackMsg.writeInt16(oid);
                AttackMsg.writeInt8(o->getDirection());
                AttackMsg.writeInt8(static_cast< Being * >(o)->getAttackId());
                gameHandler->sendTo(p, AttackMsg);
            }

            // Send action change messages.
            if ((oflags & UPDATEFLAG_ACTIONCHANGE))
            {
                MessageOut ActionMsg(GPMSG_BEING_ACTION_CHANGE);
                ActionMsg.writeInt16(oid);
                ActionMsg.writeInt8(static_cast< Being * >(o)->getAction());
                gameHandler->sendTo(p, ActionMsg);
            }

            // Send looks change messages.
            if (oflags & UPDATEFLAG_LOOKSCHANGE)
            {
                MessageOut LooksMsg(GPMSG_BEING_LOOKS_CHANGE);
                LooksMsg.writeInt16(oid);
                Character * c = static_cast<Character * >(o);
                serializeLooks(c, LooksMsg);
                LooksMsg.writeInt16(c->getHairStyle());
                LooksMsg.writeInt16(c->getHairColor());
                LooksMsg.writeInt16(c->getGender());
                gameHandler->sendTo(p, LooksMsg);
            }

            // Send emote messages.
            if (oflags & UPDATEFLAG_EMOTE)
            {
                int emoteId = o->getLastEmote();
                if (emoteId > -1)
                {
                    MessageOut EmoteMsg(GPMSG_BEING_EMOTE);
                    EmoteMsg.writeInt16(oid);
                    EmoteMsg.writeInt16(emoteId);
                    gameHandler->sendTo(p, EmoteMsg);
                }
            }

            // Send direction change messages.
            if (oflags & UPDATEFLAG_DIRCHANGE)
            {
                MessageOut DirMsg(GPMSG_BEING_DIR_CHANGE);
                DirMsg.writeInt16(oid);
                DirMsg.writeInt8(o->getDirection());
                gameHandler->sendTo(p, DirMsg);
            }

            // Send damage messages.
            if (o->canFight())
            {
                Being *victim = static_cast< Being * >(o);
                const Hits &hits = victim->getHitsTaken();
                for (Hits::const_iterator j = hits.begin(),
                     j_end = hits.end(); j != j_end; ++j)
                {
                    damageMsg.writeInt16(oid);
                    damageMsg.writeInt16(*j);
                }
            }

            if (oold == opos)
            {
                // o does not move, nothing more to report.
                continue;
            }
        }

        if (!willBeInRange)
        {
            // o is no longer visible from p. Send leave message.
            MessageOut leaveMsg(GPMSG_BEING_LEAVE);
            leaveMsg.writeInt16(oid);
            gameHandler->sendTo(p, leaveMsg);
            continue;
        }

        if (!wereInRange)
        {
            // o is now visible by p. Send enter message.
            MessageOut enterMsg(GPMSG_BEING_ENTER);
            enterMsg.writeInt8(otype);
            enterMsg.writeInt16(oid);
            enterMsg.writeInt8(static_cast< Being *>(o)->getAction());
            enterMsg.writeInt16(opos.x);
            enterMsg.writeInt16(opos.y);
            enterMsg.writeInt8(o->getDirection());
            enterMsg.writeInt8(o->getGender());
            switch (otype)
            {
                case OBJECT_CHARACTER:
                {
                    Character *q = static_cast< Character * >(o);
                    enterMsg.writeString(q->getName());
                    enterMsg.writeInt8(q->getHairStyle());
                    enterMsg.writeInt8(q->getHairColor());
                    serializeLooks(q, enterMsg);
                } break;

                case OBJECT_MONSTER:
                {
                    Monster *q = static_cast< Monster * >(o);
                    enterMsg.writeInt16(q->getSpecy()->getId());
                    enterMsg.writeString(q->getName());
                } break;

                case OBJECT_NPC:
                {
                    NpcComponent *npcComponent = o->getComponent<NpcComponent>();
                    enterMsg.writeInt16(npcComponent->getNpcId());
                    enterMsg.writeString(o->getName());
                } break;

                default:
                    assert(false); // TODO
                    break;
            }
            gameHandler->sendTo(p, enterMsg);
        }

        if (opos != oold)
        {
            // Add position check coords every 5 seconds.
            if (currentTick % 50 == 0)
                flags |= MOVING_POSITION;

            flags |= MOVING_DESTINATION;
        }

        // Send move messages.
        moveMsg.writeInt16(oid);
        moveMsg.writeInt8(flags);
        if (flags & MOVING_POSITION)
        {
            moveMsg.writeInt16(oold.x);
            moveMsg.writeInt16(oold.y);
        }

        if (flags & MOVING_DESTINATION)
        {
            moveMsg.writeInt16(opos.x);
            moveMsg.writeInt16(opos.y);
            // We multiply the sent speed (in tiles per second) by ten
            // to get it within a byte with decimal precision.
            // For instance, a value of 4.5 will be sent as 45.
            moveMsg.writeInt8((unsigned short)
                (o->getModifiedAttribute(ATTR_MOVE_SPEED_TPS) * 10));
        }
    }

    // Do not send a packet if nothing happened in p's range.
    if (moveMsg.getLength() > 2)
        gameHandler->sendTo(p, moveMsg);

    if (damageMsg.getLength() > 2)
        gameHandler->sendTo(p, damageMsg);

    // Inform client about status change.
    p->sendStatus();

    // Inform client about health change of party members
    for (CharacterIterator i(map->getWholeMapIterator()); i; ++i)
    {
        Character *c = *i;

        // Make sure its not the same character
        if (c == p)
            continue;

        // make sure they are in the same party
        if (c->getParty() == p->getParty())
        {
            int cflags = c->getUpdateFlags();
            if (cflags & UPDATEFLAG_HEALTHCHANGE)
            {
                MessageOut healthMsg(GPMSG_BEING_HEALTH_CHANGE);
                healthMsg.writeInt16(c->getPublicID());
                healthMsg.writeInt16(c->getModifiedAttribute(ATTR_HP));
                healthMsg.writeInt16(c->getModifiedAttribute(ATTR_MAX_HP));
                gameHandler->sendTo(p, healthMsg);
            }
        }
    }

    // Inform client about items on the ground around its character
    MessageOut itemMsg(GPMSG_ITEMS);
    for (FixedActorIterator it(map->getAroundBeingIterator(p, visualRange));
         it; ++it)
    {
        Actor *o = *it;

        assert(o->getType() == OBJECT_ITEM ||
               o->getType() == OBJECT_EFFECT);

        Point opos = o->getPosition();
        int oflags = o->getUpdateFlags();
        bool willBeInRange = ppos.inRangeOf(opos, visualRange);
        bool wereInRange = pold.inRangeOf(opos, visualRange) &&
                           !((pflags | oflags) & UPDATEFLAG_NEW_ON_MAP);

        if (willBeInRange ^ wereInRange)
        {
            switch (o->getType())
            {
                case OBJECT_ITEM:
                {
                    ItemComponent *item = o->getComponent<ItemComponent>();
                    ItemClass *itemClass = item->getItemClass();

                    if (oflags & UPDATEFLAG_NEW_ON_MAP)
                    {
                        /* Send a specific message to the client when an item appears
                           out of nowhere, so that a sound/animation can be performed. */
                        MessageOut appearMsg(GPMSG_ITEM_APPEAR);
                        appearMsg.writeInt16(itemClass->getDatabaseID());
                        appearMsg.writeInt16(opos.x);
                        appearMsg.writeInt16(opos.y);
                        gameHandler->sendTo(p, appearMsg);
                    }
                    else
                    {
                        itemMsg.writeInt16(willBeInRange ? itemClass->getDatabaseID() : 0);
                        itemMsg.writeInt16(opos.x);
                        itemMsg.writeInt16(opos.y);
                    }
                }
                break;
                case OBJECT_EFFECT:
                {
                    EffectComponent *e = o->getComponent<EffectComponent>();
                    e->setShown();
                    // Don't show old effects
                    if (!(oflags & UPDATEFLAG_NEW_ON_MAP))
                        break;

                    if (Being *b = e->getBeing())
                    {
                        MessageOut effectMsg(GPMSG_CREATE_EFFECT_BEING);
                        effectMsg.writeInt16(e->getEffectId());
                        effectMsg.writeInt16(b->getPublicID());
                        gameHandler->sendTo(p, effectMsg);
                    } else {
                        MessageOut effectMsg(GPMSG_CREATE_EFFECT_POS);
                        effectMsg.writeInt16(e->getEffectId());
                        effectMsg.writeInt16(opos.x);
                        effectMsg.writeInt16(opos.y);
                        gameHandler->sendTo(p, effectMsg);
                    }
                }
                break;
                default: break;
            } // Switch
        }
    }

    // Do not send a packet if nothing happened in p's range.
    if (itemMsg.getLength() > 2)
        gameHandler->sendTo(p, itemMsg);
}
Exemple #29
0
bool InputManager::handleKeyboardInput(const SDL_Event &event)
{
    bool used = false;
    bool metaKeyHeld = false;

    // Key press events
    if (event.type == SDL_KEYDOWN)
    {
        if (setupWindow->isVisible() &&
            keyboard.getNewKeyIndex() > keyboard.KEY_NO_VALUE)
        {
            keyboard.setNewKey((int) event.key.keysym.sym);
            keyboard.callbackNewKey();
            keyboard.setNewKeyIndex(keyboard.KEY_NO_VALUE);
            return false;
        }

        // If the user is configuring the keys then don't respond.
        if (!keyboard.isEnabled())
            return false;

        const int tKey = keyboard.getKeyIndex(event.key.keysym.sym);

        // Ignore input if either "ignore" key is pressed
        // Stops the character moving about if the user's window manager
        // uses "ignore+arrow key" to switch virtual desktops.
        if (keyboard.isKeyActive(keyboard.KEY_IGNORE_INPUT_1) ||
            keyboard.isKeyActive(keyboard.KEY_IGNORE_INPUT_2))
        {
            return false;
        }

        if (keyboard.isKeyLocked(event.key.keysym.sym))
            return false;

        gcn::Window *requestedWindow = NULL;

        switch (tKey)
        {
            // In-game Help
            case KeyboardConfig::KEY_WINDOW_HELP:
                requestedWindow = helpDialog;
                break;
            // Quitting confirmation dialog
            case KeyboardConfig::KEY_QUIT:
                stateManager->promptForQuit();
                used = true;
                break;
            case KeyboardConfig::KEY_WINDOW_DEBUG:
                requestedWindow = debugWindow;
                break;
            case KeyboardConfig::KEY_WINDOW_SETUP:
                requestedWindow = setupWindow;
                break;
            // Screenshot (picture, hence the p)
            case KeyboardConfig::KEY_SCREENSHOT:
                saveScreenshot();
                used = true;
                break;
        }

        if (stateManager->isInGame())
        {
            switch (tKey)
            {
                case KeyboardConfig::KEY_SCROLL_CHAT_UP:
                    if (chatWindow && chatWindow->isVisible())
                    {
                        chatWindow->scroll(-DEFAULT_CHAT_WINDOW_SCROLL);
                        used = true;
                    }
                    break;
                case KeyboardConfig::KEY_SCROLL_CHAT_DOWN:
                    if (chatWindow && chatWindow->isVisible())
                    {
                        chatWindow->scroll(DEFAULT_CHAT_WINDOW_SCROLL);
                        used = true;
                    }
                    break;
                case KeyboardConfig::KEY_WINDOW_STATUS:
                    requestedWindow = statusWindow;
                    break;
                case KeyboardConfig::KEY_WINDOW_INVENTORY:
                    requestedWindow = inventoryWindow;
                    break;
                case KeyboardConfig::KEY_WINDOW_EQUIPMENT:
                    requestedWindow = equipmentWindow;
                    break;
                case KeyboardConfig::KEY_WINDOW_SKILL:
                    requestedWindow = skillDialog;
                    break;
                case KeyboardConfig::KEY_WINDOW_MINIMAP:
                    minimap->toggle();
                    break;
                case KeyboardConfig::KEY_WINDOW_CHAT:
                    requestedWindow = chatWindow;
                    break;
                case KeyboardConfig::KEY_WINDOW_EMOTE:
                    requestedWindow = emoteWindow;
                    break;
                case KeyboardConfig::KEY_WINDOW_ITEM_SHORTCUT:
                    requestedWindow = itemShortcutWindow;
                    break;
                case KeyboardConfig::KEY_WINDOW_EMOTE_SHORTCUT:
                    requestedWindow = emoteShortcutWindow;
                    break;
                // Hide certain windows
                case KeyboardConfig::KEY_HIDE_WINDOWS:
                    statusWindow->hide();
                    inventoryWindow->hide();
                    equipmentWindow->hide();
                    skillDialog->hide();
                    chatWindow->hide();
                    itemShortcutWindow->hide();
                    setupWindow->hide();
                    debugWindow->hide();
                    emoteWindow->hide();
                    helpDialog->hide();
                    emoteShortcutWindow->hide();
                    minimap->hide();
                    used = true;
                    break;
                // Find path to mouse (debug purpose)
                case KeyboardConfig::KEY_PATHFIND:
                    viewport->toggleDebugPath();
                    used = true;
                    break;
                default:
                    break;
            }

            metaKeyHeld = keyboard.isKeyActive(keyboard.KEY_METAKEY);

            for (int i = 0; i <= SHORTCUTS; i++)
            {
                ShortcutHandler *shortcut = metaKeyHeld ? (ShortcutHandler *) emoteShortcut :
                                                          (ShortcutHandler *) itemShortcut;
                const int offset = metaKeyHeld ? KeyboardConfig::KEY_EMOTE_SHORTCUT_1 :
                                                 KeyboardConfig::KEY_ITEM_SHORTCUT_1;

                if (keyboard.isKeyActive(i + offset))
                {
                    shortcut->useShortcut(i);
                    used = true;
                    break;
                }
            }

            if (keyboard.isKeyActive(keyboard.KEY_TOGGLE_CHAT) && chatWindow)
            {
                chatWindow->requestChatFocus();
                used = true;
            }

            // Player actions
            if (player_node && player_node->mAction != Being::DEAD)
            {
                Being *target = player_node->getTarget();
                const Uint16 x = player_node->mX;
                const Uint16 y = player_node->mY;

                if (!keyboard.isKeyActive(keyboard.KEY_CLEAR_TARGET))
                {
                    Being::Type type = Being::INVALID;

                    // Target the nearest monster
                    if (keyboard.isKeyActive(keyboard.KEY_TARGET_MONSTER))
                        type = Being::MONSTER;
                    // Target the nearest player
                    else if (keyboard.isKeyActive(keyboard.KEY_TARGET_PLAYER))
                        type = Being::PLAYER;
                    // Target the nearest npc
                    else if (keyboard.isKeyActive(keyboard.KEY_TARGET_NPC))
                        type = Being::NPC;

                    target = beingManager->findNearestLivingBeing(x, y, 20,
                                           type != Being::INVALID ? type :
                                                   Being::UNKNOWN);

                    if (type != Being::INVALID && !targetKeyHeld)
                    {
                        player_node->setTarget(target);
                        targetKeyHeld = true;
                        used = true;
                    }
                    else if (player_node->isAttacking())
                        target = NULL;

                    if (keyboard.isKeyActive(keyboard.KEY_ATTACK) && target)
                    {
                        player_node->attack(player_node->getTarget() ?
                                            player_node->getTarget() : target,
                                            target->getType() != Being::NPC);
                        used = true;
                    }
                }
                // Stop attacking
                else if (keyboard.isKeyActive(keyboard.KEY_CLEAR_TARGET))
                {
                    player_node->stopAttack();
                    targetKeyHeld = false;
                }

                if (keyboard.isKeyActive(keyboard.KEY_BEING_MENU))
                {
                    target = player_node->getTarget();

                    if (!target)
                        target = beingManager->findNearestLivingBeing(x, y, 20);

                    if (target)
                    {
                        Map *map = viewport->getMap();
                        viewport->showPopup(target->mX * map->getTileWidth() -
                                            viewport->getCameraX() +
                                           (map->getTileWidth() / 2),
                                            target->mY * map->getTileHeight() -
                                            viewport->getCameraY(), target);
                    }
                    used = true;
                }

                switch (tKey)
                {
                    case KeyboardConfig::KEY_PICKUP:
                        {
                            Uint16 x = player_node->mX;
                            Uint16 y = player_node->mY;
                            FloorItem *item = floorItemManager->
                                                  findNearestItem(x, y);

                            if (item)
                                player_node->pickUp(item);

                            used = true;
                        }
                        break;
                    // Player sit action
                    case KeyboardConfig::KEY_SIT:
                        player_node->toggleSit();
                        used = true;
                        break;
                    // Toggle accepting of incoming trade requests
                    case KeyboardConfig::KEY_TRADE:
                        {
                            unsigned int deflt = player_relations.getDefault();
                            if (deflt & PlayerRelation::TRADE)
                            {
                                chatWindow->chatLog(_("Ignoring incoming "
                                                      "trade requests"),
                                                      Palette::SYSTEM);
                                deflt &= ~PlayerRelation::TRADE;
                            }
                            else
                            {
                                chatWindow->chatLog(_("Accepting incoming "
                                                      "trade requests"),
                                                      Palette::SYSTEM);
                                deflt |= PlayerRelation::TRADE;
                            }

                            player_relations.setDefault(deflt);
                            used = true;
                        }
                        break;
               }
            }
        }

        if (requestedWindow)
        {
            requestedWindow->setVisible(!requestedWindow->isVisible());
            used = true;
        }
    }
    else if (event.type == SDL_KEYUP)
    {
        const int tKey = keyboard.getKeyIndex(event.key.keysym.sym);

        // Stop protecting the target keys
        if (tKey == KeyboardConfig::KEY_TARGET_MONSTER ||
            tKey == KeyboardConfig::KEY_TARGET_PLAYER || 
            tKey == KeyboardConfig::KEY_TARGET_NPC)
        {
            targetKeyHeld = false;
        }
    }

    // At the moment, this is the only bit of logic left not assigned to a
    // specific SDL input poll, because it was causing continuous walking
    // without stopping. It would be better in the long run if this would get
    // fixed and then moved to one of them (in case we ever use other input
    // libraries. If everything is already grouped together, it'd be easier to
    // adapt to a new library, instead of having to rely on special cases)
    if (stateManager->isInGame() && player_node->mAction != Being::DEAD && !used)
    {
        unsigned char direction = 0;

        // Get the state of the keyboard keys
        keyboard.refreshActiveKeys();

        // Translate pressed keys to movement and direction
        if (keyboard.isKeyActive(keyboard.KEY_MOVE_UP))
            direction |= Being::UP;
        else if (keyboard.isKeyActive(keyboard.KEY_MOVE_DOWN))
            direction |= Being::DOWN;

        if (keyboard.isKeyActive(keyboard.KEY_MOVE_LEFT))
            direction |= Being::LEFT;
        else if (keyboard.isKeyActive(keyboard.KEY_MOVE_RIGHT))
            direction |= Being::RIGHT;

        if (metaKeyHeld && direction != 0)
            player_node->setDirection(direction);
        else
            player_node->setWalkingDir(direction);
    }

    return used;
}
Exemple #30
0
void InputManager::handleJoystickInput(const SDL_Event &event)
{
    if (joystick)
        joystick->update();
    else
        return;

    if (!stateManager->isInGame())
        return;

    if (event.type == SDL_JOYBUTTONUP && !joystick->buttonPressed(3))
    {
        targetKeyHeld = false; // Stop protecting the target key
    }
    else if (player_node && player_node->mAction != Being::DEAD)
    {
        const Uint16 x = player_node->mX;
        const Uint16 y = player_node->mY;

        if (!keyboard.isKeyActive(keyboard.KEY_CLEAR_TARGET))
        {
            Being *target = player_node->getTarget();

            // Target the nearest monster
            if (joystick->buttonPressed(3) && !targetKeyHeld)
            {
                target = beingManager->findNearestLivingBeing(x, y, 20,
                                                              Being::MONSTER);
                player_node->setTarget(target);
                targetKeyHeld = true;
            }

            if (joystick->buttonPressed(0) && target &&
                target->getType() != Being::NPC)
            {
                player_node->attack(target, true);
            }
        }

        if (joystick->buttonPressed(1))
        {
            FloorItem *item = floorItemManager->findByCoordinates(x, y);

            if (item)
                player_node->pickUp(item);
        }

        if (joystick->buttonPressed(2))
            player_node->toggleSit();

        unsigned char direction = 0;

        // Translate pressed keys to movement and direction
        if (joystick->isUp())
            direction |= Being::UP;
        else if (joystick->isDown())
            direction |= Being::DOWN;

        if (joystick->isLeft())
            direction |= Being::LEFT;
        else if (joystick->isRight())
            direction |= Being::RIGHT;

        player_node->setWalkingDir(direction);
    }
}