void ProtocolSpectator::addDummyCreature(NetworkMessage& msg, const uint32_t& creatureID, const Position& playerPos) { // add dummy creature CreatureType_t creatureType = CREATURETYPE_NPC; if(creatureID <= 0x10000000) { creatureType = CREATURETYPE_PLAYER; } else if(creatureID <= 0x40000000) { creatureType = CREATURETYPE_MONSTER; } msg.addByte(0x6A); msg.addPosition(playerPos); msg.addByte(1); //stackpos msg.add<uint16_t>(0x61); // is not known msg.add<uint32_t>(0); // remove no creature msg.add<uint32_t>(creatureID); // creature id msg.addByte(creatureType); // creature type msg.addString("Dummy"); msg.addByte(0x00); // health percent msg.addByte(DIRECTION_NORTH); // direction AddOutfit(msg, player->getCurrentOutfit()); // outfit msg.addByte(0); // light level msg.addByte(0); // light color msg.add<uint16_t>(200); // speed msg.addByte(SKULL_NONE); // skull type msg.addByte(SHIELD_NONE); // party shield msg.addByte(GUILDEMBLEM_NONE); // guild emblem msg.addByte(creatureType); // creature type msg.addByte(SPEECHBUBBLE_NONE); // speechbubble msg.addByte(0xFF); // MARK_UNMARKED msg.add<uint16_t>(0x00); // helpers msg.addByte(0); // walkThrough }
void ProtocolGameBase::sendMapDescription(const Position& pos) { NetworkMessage msg; msg.addByte(0x64); msg.addPosition(player->getPosition()); GetMapDescription(pos.x - 8, pos.y - 6, pos.z, 18, 14, msg); writeToOutputBuffer(msg); }
//tile void ProtocolGameBase::RemoveTileThing(NetworkMessage& msg, const Position& pos, uint32_t stackpos) { if (stackpos >= 10) { return; } msg.addByte(0x6C); msg.addPosition(pos); msg.addByte(stackpos); }
void ProtocolGameBase::sendMagicEffect(const Position& pos, uint8_t type) { if (!canSee(pos)) { return; } NetworkMessage msg; msg.addByte(0x83); msg.addPosition(pos); msg.addByte(type); writeToOutputBuffer(msg); }
void ProtocolSpectator::sendEmptyTileOnPlayerPos(const Tile* tile, const Position& playerPos) { NetworkMessage msg; msg.addByte(0x69); msg.addPosition(playerPos); msg.add<uint16_t>(0x00); msg.addItem(tile->getGround()); msg.addByte(0x00); msg.addByte(0xFF); writeToOutputBuffer(msg); }
void ProtocolGameBase::sendUpdateTile(const Tile* tile, const Position& pos) { if (!canSee(pos)) { return; } NetworkMessage msg; msg.addByte(0x69); msg.addPosition(pos); if (tile) { GetTileDescription(tile, msg); msg.addByte(0x00); msg.addByte(0xFF); } else { msg.addByte(0x01); msg.addByte(0xFF); } writeToOutputBuffer(msg); }
void ProtocolSpectator::syncKnownCreatureSets() { const auto& casterKnownCreatures = client->getKnownCreatures(); const auto playerPos = player->getPosition(); const auto tile = player->getTile(); if (!tile || !tile->getGround()) { disconnectSpectator("A sync error has occured."); return; } sendEmptyTileOnPlayerPos(tile, playerPos); bool known; uint32_t removedKnown; for (const auto creatureID : casterKnownCreatures) { if (knownCreatureSet.find(creatureID) != knownCreatureSet.end()) { continue; } NetworkMessage msg; const auto creature = g_game.getCreatureByID(creatureID); if (creature && !creature->isRemoved()) { msg.addByte(0x6A); msg.addPosition(playerPos); msg.addByte(1); //stackpos checkCreatureAsKnown(creature->getID(), known, removedKnown); AddCreature(msg, creature, known, removedKnown); RemoveTileThing(msg, playerPos, 1); } else if (operatingSystem <= CLIENTOS_FLASH) { // otclient freeze with huge amount of creature add, but do not debug if there are unknown creatures, best solution for now :( addDummyCreature(msg, creatureID, playerPos); RemoveTileThing(msg, playerPos, 1); } writeToOutputBuffer(msg); } sendUpdateTile(tile, playerPos); }
void ProtocolGameBase::sendAddCreature(const Creature* creature, const Position& pos, int32_t stackpos, bool isLogin) { if (!canSee(pos)) { return; } if (creature != player) { if (stackpos != -1) { NetworkMessage msg; msg.addByte(0x6A); msg.addPosition(pos); msg.addByte(stackpos); bool known; uint32_t removedKnown; checkCreatureAsKnown(creature->getID(), known, removedKnown); AddCreature(msg, creature, known, removedKnown); writeToOutputBuffer(msg); } if (isLogin) { sendMagicEffect(pos, CONST_ME_TELEPORT); } return; } NetworkMessage msg; msg.addByte(0x17); msg.add<uint32_t>(player->getID()); msg.add<uint16_t>(0x32); // beat duration (50) msg.addDouble(Creature::speedA, 3); msg.addDouble(Creature::speedB, 3); msg.addDouble(Creature::speedC, 3); // can report bugs? if (player->getAccountType() >= ACCOUNT_TYPE_TUTOR) { msg.addByte(0x01); } else { msg.addByte(0x00); } msg.addByte(0x00); // can change pvp framing option msg.addByte(0x00); // expert mode button enabled msg.addString("http://static.tibia.com/images/store/"); msg.addByte(3); writeToOutputBuffer(msg); sendPendingStateEntered(); sendEnterWorld(); sendMapDescription(pos); if (isLogin) { sendMagicEffect(pos, CONST_ME_TELEPORT); } sendInventoryItem(CONST_SLOT_HEAD, player->getInventoryItem(CONST_SLOT_HEAD)); sendInventoryItem(CONST_SLOT_NECKLACE, player->getInventoryItem(CONST_SLOT_NECKLACE)); sendInventoryItem(CONST_SLOT_BACKPACK, player->getInventoryItem(CONST_SLOT_BACKPACK)); sendInventoryItem(CONST_SLOT_ARMOR, player->getInventoryItem(CONST_SLOT_ARMOR)); sendInventoryItem(CONST_SLOT_RIGHT, player->getInventoryItem(CONST_SLOT_RIGHT)); sendInventoryItem(CONST_SLOT_LEFT, player->getInventoryItem(CONST_SLOT_LEFT)); sendInventoryItem(CONST_SLOT_LEGS, player->getInventoryItem(CONST_SLOT_LEGS)); sendInventoryItem(CONST_SLOT_FEET, player->getInventoryItem(CONST_SLOT_FEET)); sendInventoryItem(CONST_SLOT_RING, player->getInventoryItem(CONST_SLOT_RING)); sendInventoryItem(CONST_SLOT_AMMO, player->getInventoryItem(CONST_SLOT_AMMO)); sendStats(); sendSkills(); //gameworld light-settings LightInfo lightInfo; g_game.getWorldLightInfo(lightInfo); sendWorldLight(lightInfo); //player light level sendCreatureLight(creature); const std::forward_list<VIPEntry>& vipEntries = IOLoginData::getVIPEntries(player->getAccount()); if (player->isAccessPlayer()) { for (const VIPEntry& entry : vipEntries) { VipStatus_t vipStatus; Player* vipPlayer = g_game.getPlayerByGUID(entry.guid); if (!vipPlayer) { vipStatus = VIPSTATUS_OFFLINE; } else { vipStatus = VIPSTATUS_ONLINE; } sendVIP(entry.guid, entry.name, entry.description, entry.icon, entry.notify, vipStatus); } } else { for (const VIPEntry& entry : vipEntries) { VipStatus_t vipStatus; Player* vipPlayer = g_game.getPlayerByGUID(entry.guid); if (!vipPlayer || vipPlayer->isInGhostMode()) { vipStatus = VIPSTATUS_OFFLINE; } else { vipStatus = VIPSTATUS_ONLINE; } sendVIP(entry.guid, entry.name, entry.description, entry.icon, entry.notify, vipStatus); } } sendBasicData(); sendInventory(); player->sendIcons(); }