Being *BeingManager::findNearestLivingBeing(Being *aroundBeing, int maxdist, Being::Type type) const { Being *closestBeing = NULL; int dist = 0; int x = aroundBeing->mX; int y = aroundBeing->mY; for (Beings::const_iterator i = mBeings.begin(), i_end = mBeings.end(); i != i_end; ++i) { Being *being = (*i); int d = std::max(abs(being->mX - x), abs(being->mY - y)); if ((being->getType() == type || type == Being::UNKNOWN) && (d < dist || closestBeing == NULL) // it is closer && being->mAction != Being::DEAD // no dead beings && being != aroundBeing) { dist = d; closestBeing = being; } } return (maxdist >= dist) ? closestBeing : NULL; }
Being *BeingManager::findNearestLivingBeing(int x, int y, int maxdist, Being::Type type) const { Being *closestBeing = NULL; int dist = 0; Beings::const_iterator itr = mBeings.begin(); Beings::const_iterator itr_end = mBeings.end(); for (; itr != itr_end; ++itr) { Being *being = (*itr); int d = std::max(abs(being->mX - x), abs(being->mY - y)); if ((being->getType() == type || (type == Being::UNKNOWN && being->getType() != Being::WARP)) && (d < dist || closestBeing == NULL) // it is closer && being->mAction != Being::DEAD // no dead beings && being != player_node) // it is not you { dist = d; closestBeing = being; } } return (maxdist >= dist) ? closestBeing : NULL; }
Being *BeingManager::findNearestLivingBeing(int x, int y, int maxTileDist, Being::Type type) const { Being *closestBeing = 0; int dist = 0; const int maxDist = maxTileDist * 32; Beings::const_iterator itr = mBeings.begin(); Beings::const_iterator itr_end = mBeings.end(); for (; itr != itr_end; ++itr) { Being *being = (*itr); const Vector &pos = being->getPosition(); int d = abs(((int) pos.x) - x) + abs(((int) pos.y) - y); if ((being->getType() == type || type == Being::UNKNOWN) && (d < dist || !closestBeing) // it is closer && being->isAlive()) // no dead beings { dist = d; closestBeing = being; } } return (maxDist >= dist) ? closestBeing : 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)); }
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; } }
void BeingManager::updatePlayerNames() { Beings::iterator i = mBeings.begin(); while (i != mBeings.end()) { Being *being = (*i); if (being->getType() == Being::PLAYER && being->getName() != "") being->updateName(); ++i; } }
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); } }
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); } }
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; }
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)); } }
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; } } }
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); } }
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; } }
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); } }
void PopupMenu::handleLink(const std::string &link) { Being *being = beingManager->findBeing(mBeingId); // Talk To actiondar : if (link == "talk" && being && being->getType() == Being::NPC && current_npc == 0) { dynamic_cast<NPC*>(being)->talk(); } // Trade action else if (link == "trade" && being && being->getType() == Being::PLAYER) { Net::getTradeHandler()->request(being); tradePartnerName = being->getName(); } // Attack action else if (link == "attack" && being) { player_node->attack(being, true); } else if (link == "unignore" && being && being->getType() == Being::PLAYER) { player_relations.setRelation(being->getName(), PlayerRelation::NEUTRAL); } else if (link == "ignore" && being && being->getType() == Being::PLAYER) { player_relations.setRelation(being->getName(), PlayerRelation::IGNORED); } else if (link == "disregard" && being && being->getType() == Being::PLAYER) { player_relations.setRelation(being->getName(), PlayerRelation::DISREGARDED); } else if (link == "friend" && being && being->getType() == Being::PLAYER) { player_relations.setRelation(being->getName(), PlayerRelation::FRIEND); } #ifdef TMWSERV_SUPPORT // Guild action else if (link == "guild" && being != NULL && being->getType() == Being::PLAYER) { player_node->inviteToGuild(being); } #endif /* // Follow Player action else if (link == "follow") { }*/ /* // Add Buddy action else if ((link == "buddy") && being && being->isPlayer()) { if (!buddyWindow->isVisible()) buddyWindow->setVisible(true); buddyWindow->addBuddy(being->getName()); }*/ // Pick Up Floor Item action else if ((link == "pickup") && mFloorItem) { player_node->pickUp(mFloorItem); } // Look To action else if (link == "look") { } else if (link == "use") { assert(mItem); if (mItem->isEquipment()) { if (mItem->isEquipped()) Net::getInventoryHandler()->unequipItem(mItem); else Net::getInventoryHandler()->equipItem(mItem); } else { Net::getInventoryHandler()->useItem(mItem); } } else if (link == "chat") { chatWindow->addItemText(mItem->getInfo().getName()); } else if (link == "split") { ItemAmountWindow::showWindow(ItemAmountWindow::ItemSplit, inventoryWindow, mItem); } else if (link == "drop") { ItemAmountWindow::showWindow(ItemAmountWindow::ItemDrop, inventoryWindow, mItem); } else if (link == "store") { ItemAmountWindow::showWindow(ItemAmountWindow::StoreAdd, inventoryWindow, mItem); } else if (link == "retrieve") { ItemAmountWindow::showWindow(ItemAmountWindow::StoreRemove, storageWindow, mItem); } else if (link == "party" && being && being->getType() == Being::PLAYER) { Net::getPartyHandler()->invite(dynamic_cast<Player*>(being)); } else if (link == "name" && being) { const std::string &name = being->getName(); chatWindow->addInputText("/w "+name); } else if (link == "admin-kick" && being && (being->getType() == Being::PLAYER || being->getType() == Being::MONSTER)) { Net::getAdminHandler()->kick(being->getId()); } // Unknown actions else if (link != "cancel") { logger->log("PopupMenu: Warning, unknown action '%s'", link.c_str()); } setVisible(false); mBeingId = 0; mFloorItem = NULL; mItem = NULL; }
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; }
void PopupMenu::handleLink(const std::string &link) { Being *being = actorSpriteManager->findBeing(mBeingId); // Talk To action if (link == "talk" && being && being->canTalk()) { being->talkTo(); } // Trade action else if (link == "trade" && being && being->getType() == ActorSprite::PLAYER) { Net::getTradeHandler()->request(being); tradePartnerName = being->getName(); } // Attack action else if (link == "attack" && being) { player_node->attack(being, true); } else if (link == "whisper" && being) { chatWindow->addInputText("/w \"" + being->getName() + "\" "); } else if (link == "unignore" && being && being->getType() == ActorSprite::PLAYER) { player_relations.setRelation(being->getName(), PlayerRelation::NEUTRAL); } else if (link == "ignore" && being && being->getType() == ActorSprite::PLAYER) { player_relations.setRelation(being->getName(), PlayerRelation::IGNORED); } else if (link == "disregard" && being && being->getType() == ActorSprite::PLAYER) { player_relations.setRelation(being->getName(), PlayerRelation::DISREGARDED); } else if (link == "friend" && being && being->getType() == ActorSprite::PLAYER) { player_relations.setRelation(being->getName(), PlayerRelation::FRIEND); } // Guild action else if (link == "guild" && being && being->getType() == ActorSprite::PLAYER) { player_node->inviteToGuild(being); } // Follow Player action else if (link == "follow" && being) { player_node->setFollow(being->getName()); } // Pick Up Floor Item action else if ((link == "pickup") && mFloorItem) { player_node->pickUp(mFloorItem); } // Look To action else if (link == "look") { } else if (link == "use") { assert(mItem); if (mItem->isEquipment()) { if (mItem->isEquipped()) Net::getInventoryHandler()->unequipItem(mItem); else Net::getInventoryHandler()->equipItem(mItem); } else { Net::getInventoryHandler()->useItem(mItem); } } else if (link == "chat") { if (mItem) chatWindow->addItemText(mItem->getInfo().getName()); else if (mFloorItem) chatWindow->addItemText(mFloorItem->getInfo().getName()); } else if (link == "split") { ItemAmountWindow::showWindow(ItemAmountWindow::ItemSplit, inventoryWindow, mItem); } else if (link == "drop") { ItemAmountWindow::showWindow(ItemAmountWindow::ItemDrop, inventoryWindow, mItem); } else if (link == "store") { ItemAmountWindow::showWindow(ItemAmountWindow::StoreAdd, inventoryWindow, mItem); } else if (link == "retrieve") { ItemAmountWindow::showWindow(ItemAmountWindow::StoreRemove, mWindow, mItem); } else if (link == "party" && being && being->getType() == ActorSprite::PLAYER) { Net::getPartyHandler()->invite(being); } else if (link == "name" && being) { const std::string &name = being->getName(); chatWindow->addInputText(name); } else if (link == "admin-kick" && being && (being->getType() == ActorSprite::PLAYER || being->getType() == ActorSprite::MONSTER)) { Net::getAdminHandler()->kick(being->getId()); } // Unknown actions else if (link != "cancel") { logger->log("PopupMenu: Warning, unknown action '%s'", link.c_str()); } setVisible(false); mBeingId = 0; mFloorItem = NULL; mItem = NULL; }
void PartyHandler::handleMessage(MessageIn *msg) { switch (msg->getId()) { case SMSG_PARTY_CREATE: mParty->createResponse(msg->readInt8()); break; case SMSG_PARTY_INFO: break; case SMSG_PARTY_INVITE: { std::string nick = msg->readString(24); int status = msg->readInt8(); mParty->inviteResponse(nick, status); break; } case SMSG_PARTY_INVITED: { int id = msg->readInt32(); Being *being = beingManager->findBeing(id); if (!being) { break; } std::string nick; int gender = 0; std::string partyName = ""; if (being->getType() != Being::PLAYER) { nick = ""; } else { nick = being->getName(); gender = being->getGender(); partyName = msg->readString(24); } mParty->invitedAsk(nick, gender, partyName); break; } case SMSG_PARTY_SETTINGS: break; case SMSG_PARTY_MEMBER_INFO: break; case SMSG_PARTY_LEAVE: { /*int id = */msg->readInt32(); std::string nick = msg->readString(24); /*int fail = */msg->readInt8(); mParty->leftResponse(nick); break; } case SMSG_PARTY_UPDATE_HP: break; case SMSG_PARTY_UPDATE_COORDS: break; case SMSG_PARTY_MESSAGE: { // new block to enable local variables int msgLength = msg->readInt16() - 8; if (msgLength <= 0) return; int id = msg->readInt32(); Being *being = beingManager->findBeing(id); std::string chatMsg = msg->readString(msgLength); mParty->receiveChat(being, chatMsg); } break; } }
void ChatHandler::handleMessage(MessageIn &msg) { Being *being; std::string chatMsg; std::string nick; int chatMsgLength; switch (msg.getId()) { case SMSG_WHISPER_RESPONSE: if (mSentWhispers.empty()) nick = "user"; else { nick = mSentWhispers.front(); mSentWhispers.pop(); } switch (msg.readInt8()) { case 0x00: // Success (don't need to report) break; case 0x01: { Event event(Event::WhisperError); event.setString("nick", nick); event.setString("error", strprintf(_("Whisper could " "not be sent, %s is offline."), nick.c_str())); event.trigger(Event::ChatChannel); } break; case 0x02: { Event event(Event::WhisperError); event.setString("nick", nick); event.setString("error", strprintf(_("Whisper could " "not be sent, ignored by %s."), nick.c_str())); event.Event::trigger(Event::ChatChannel); } break; } break; // Received whisper case SMSG_WHISPER: chatMsgLength = msg.readInt16() - 28; nick = msg.readString(24); if (chatMsgLength <= 0) break; chatMsg = msg.readString(chatMsgLength); // This is a sure sign of some special command, none of which are // supported at the moment. if (chatMsg.compare(0, 3, "\302\202!") == 0) return; if (nick != "Server") { // Ignore the shop commands since this client doesn't support // them at the moment. if (chatMsg.find("!selllist ") == 0 || chatMsg.find("!buylist ") == 0 || chatMsg.find("!buyitem ") == 0 || chatMsg.find("!sellitem ") == 0) return; if (player_relations.hasPermission(nick, PlayerRelation::WHISPER)) { Event event(Event::Whisper); event.setString("nick", nick); event.setString("message", chatMsg); event.trigger(Event::ChatChannel); } } else { SERVER_NOTICE(chatMsg) } break; // Received speech from being case SMSG_BEING_CHAT: { chatMsgLength = msg.readInt16() - 8; int beingId = msg.readInt32(); being = actorSpriteManager->findBeing(beingId); if (!being || chatMsgLength <= 0) break; chatMsg = msg.readString(chatMsgLength); std::string::size_type pos = chatMsg.find(" : ", 0); std::string sender_name = ((pos == std::string::npos) ? "" : chatMsg.substr(0, pos)); if (sender_name != being->getName() && being->getType() == Being::PLAYER) { if (!being->getName().empty()) sender_name = being->getName(); } else { chatMsg.erase(0, pos + 3); } int perms; if (being->getType() == Being::PLAYER) { perms = player_relations.checkPermissionSilently(sender_name, PlayerRelation::SPEECH_LOG | PlayerRelation::SPEECH_FLOAT); } else { perms = player_relations.getDefault() & (PlayerRelation::SPEECH_LOG | PlayerRelation::SPEECH_FLOAT); } trim(chatMsg); std::string reducedMessage = chatMsg; chatMsg = removeColors(sender_name) + " : " + reducedMessage; Event event(Event::Being); event.setString("message", chatMsg); event.setString("text", reducedMessage); event.setString("nick", sender_name); event.setInt("beingId", beingId); event.setInt("permissions", perms); event.trigger(Event::ChatChannel); break; } case SMSG_PLAYER_CHAT: case SMSG_GM_CHAT: { chatMsgLength = msg.readInt16() - 4; if (chatMsgLength <= 0) break; chatMsg = msg.readString(chatMsgLength); if (msg.getId() == SMSG_PLAYER_CHAT) { std::string::size_type pos = chatMsg.find(" : ", 0); std::string mes = chatMsg; if (pos != std::string::npos) chatMsg.erase(0, pos + 3); trim(chatMsg); Event event(Event::Player); event.setString("message", mes); event.setString("text", chatMsg); event.setString("nick", local_player->getName()); event.setInt("beingId", local_player->getId()); event.setInt("permissions", player_relations.getDefault() & (PlayerRelation::SPEECH_LOG | PlayerRelation::SPEECH_FLOAT)); event.trigger(Event::ChatChannel); } else { Event event(Event::Announcement); event.setString("message", chatMsg); event.trigger(Event::ChatChannel); } break; } case SMSG_MVP: // Display MVP player msg.readInt32(); // id SERVER_NOTICE(_("MVP player.")) break; } }
/** * 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); }
void Viewport::mousePressed(gcn::MouseEvent &event) { if (event.getSource() != this) return; // Check if we are alive and kickin' if (!mCurrentMap || !player_node || player_node->mAction == Being::DEAD) return; mPlayerFollowMouse = false; const int tileWidth = mCurrentMap->getTileWidth(); const int tileHeight = mCurrentMap->getTileHeight(); const int tilex = event.getX() / tileWidth + mTileViewX; const int tiley = event.getY() / tileHeight + mTileViewY; const int x = (int)((float) event.getX() + mPixelViewX); const int y = (int)((float) event.getY() + mPixelViewY); // Right click might open a popup if (event.getButton() == gcn::MouseEvent::RIGHT) { Being *being; FloorItem *floorItem; if ((being = beingManager->findBeingByPixel(x, y)) && being != player_node) { mPopupMenu->setType(BEING); showPopup(event.getX(), event.getY(), being); return; } else if ((floorItem = floorItemManager->findByCoordinates(tilex, tiley))) { mPopupMenu->setType(FLOOR_ITEM); mPopupMenu->setFloorItem(floorItem); mPopupMenu->showPopup(event.getX(), event.getY()); return; } } // If a popup is active, just remove it if (mPopupMenu->isVisible()) { mPopupMenu->setVisible(false); return; } // Left click can cause different actions if (event.getButton() == gcn::MouseEvent::LEFT) { Being *being; FloorItem *item; // Interact with some being // if ((being = beingManager->findBeing(tilex, tiley))) if ((being = beingManager->findBeingByPixel(x, y)) && being->mAction != Being::DEAD) { if (being->getType() == Being::NPC && NPC::mTalking == false) static_cast<NPC*>(being)->talk(); else if (player_node->withinAttackRange(being) && being->getType() != Being::NPC) { player_node->setGotoTarget(being); player_node->attack(being, true); } else player_node->setDestination(tilex, tiley); } // Pick up some item else if ((item = floorItemManager->findByCoordinates(tilex, tiley))) player_node->pickUp(item); else if (player_node->mAction == Being::SIT) return; // Just walk around else { player_node->stopAttack(); player_node->setDestination(tilex, tiley); mPlayerFollowMouse = true; } } else if (event.getButton() == gcn::MouseEvent::MIDDLE) { // Find the being nearest to the clicked position Being *target = beingManager->findBeingByPixel(x, y); if (target) player_node->setTarget(target); } }