void ObjectController::_handleDestroyInstrument(Item* item) { PlayerObject* playerObject = dynamic_cast<PlayerObject*>(mObject); Item* tempInstrument = NULL; Item* permanentInstrument = NULL; // first, stop playing, if its currently in use if(playerObject->getPerformingState() == PlayerPerformance_Music) { // equipped instrument if(item == dynamic_cast<Item*>(playerObject->getEquipManager()->getEquippedObject(CreatureEquipSlot_Instrument)) || playerObject->getPlacedInstrumentId()) { gEntertainerManager->stopEntertaining(playerObject); } } // handle destruction of instanced instruments, placed in world if(playerObject->getPlacedInstrumentId()) { // get the instruments tempInstrument = dynamic_cast<Item*>(gWorldManager->getObjectById(playerObject->getPlacedInstrumentId())); if(!tempInstrument) { gLogger->logMsg("ObjectController::handleDestroyInstrument : no temporary Instrument\n"); return; } permanentInstrument = dynamic_cast<Item*>(gWorldManager->getObjectById(tempInstrument->getPersistantCopy())); if(!permanentInstrument) { gLogger->logMsg("ObjectController::handleDestroyInstrument : no parent Instrument\n"); return; } // the temporary gets ALWAYS deleted // update the attributes of the permanent Instrument if(tempInstrument == item) { permanentInstrument->setPlaced(false); permanentInstrument->setNonPersistantCopy(0); playerObject->setPlacedInstrumentId(0); } // it is the permanent Instrument delete the temporary copy too else if(permanentInstrument == item) { destroyObject(tempInstrument->getId()); } } }
void Instrument::prepareCustomRadialMenu(CreatureObject* player, uint8 itemCount) { // NOTE: player is also of type CreatureObject* !!! PlayerObject* playerObject = dynamic_cast<PlayerObject*>(player); mRadialMenu.reset(); mRadialMenu = RadialMenuPtr(new RadialMenu()); // RadialMenu* radial = new RadialMenu(); //string mInstrumentString = instrument->getName(); uint32 instrumentNr = this->getItemType(); if ((instrumentNr == ItemType_Nalargon) || (instrumentNr == ItemType_omni_box) || (instrumentNr == ItemType_nalargon_max_reebo)) { uint32 radId = 1; // We have to know if this is the real one or the copy. if (playerObject->getPlacedInstrumentId() == this->getId()) { // We are handling the copy if ((playerObject->getId() == this->getOwner()) && this->getPlaced()) { if ((playerObject->getPerformingState() == PlayerPerformance_Music)) { mRadialMenu->addItem(static_cast<uint8>(radId++),0,radId_itemUse,radAction_ObjCallback, "@radial_performance:stop_playing"); } else { mRadialMenu->addItem(static_cast<uint8>(radId++),0,radId_itemUse,radAction_ObjCallback, "@radial_performance:play_instrument"); } } else { // radial->addItem(radId++,0,radId_examine,radAction_Default); // radial->addItem(radId++,0,radId_itemPickup,radAction_Default); return; } mRadialMenu->addItem(static_cast<uint8>(radId++),0,radId_examine,radAction_Default); mRadialMenu->addItem(static_cast<uint8>(radId++),0,radId_itemPickup,radAction_Default); } else { // We may be handling the original instrument. Inventory* inventory = dynamic_cast<Inventory*>(playerObject->getEquipManager()->getEquippedObject(CreatureEquipSlot_Inventory)); if (inventory) { if (inventory->getId() == this->getParentId()) { // We have our real instrument in the inventory. // We can't drop if outside in the world. if (player->getParentId() == 0) { // Outside mRadialMenu->addItem(static_cast<uint8>(radId++),0,radId_examine,radAction_Default); mRadialMenu->addItem(static_cast<uint8>(radId),0,radId_itemDestroy, radAction_Default); } else { mRadialMenu->addItem(static_cast<uint8>(radId++),0,radId_examine,radAction_Default); mRadialMenu->addItem(static_cast<uint8>(radId),0,radId_itemDrop,radAction_Default); mRadialMenu->addItem(static_cast<uint8>(radId),0,radId_itemDestroy, radAction_Default); } if (playerObject->getPlacedInstrumentId() == 0) { // We do not have any other placed intrument out. mRadialMenu->addItem(static_cast<uint8>(radId++),0,radId_itemUse,radAction_ObjCallback,"Use"); } } else if (dynamic_cast<CellObject*>(gWorldManager->getObjectById(this->getParentId()))) { // It's either a original instrument, or someone else instrument, copy or original. // Time for some dirty... the original instrument does not have an owner. // Let's take advantage of that shortcoming. // Is this my instrument? if (this->getOwner() == player->getId()) { // Yes, are we handling the original instrument. // if (cell->getId() == this->getParentId()) { if ((playerObject->getPerformingState() == PlayerPerformance_Music)) { mRadialMenu->addItem(static_cast<uint8>(radId++),0,radId_itemUse,radAction_ObjCallback, "@radial_performance:stop_playing"); } else { mRadialMenu->addItem(static_cast<uint8>(radId++),0,radId_itemUse,radAction_ObjCallback, "@radial_performance:play_instrument"); } mRadialMenu->addItem(static_cast<uint8>(radId++),0,radId_examine,radAction_Default); mRadialMenu->addItem(static_cast<uint8>(radId++),0,radId_itemPickup,radAction_Default); } } else { // This is not my instrument. // gMessageLib->sendSystemMessage(playerObject,L"","error_message","insufficient_permissions"); mRadialMenu->addItem(static_cast<uint8>(radId++),0,radId_examine,radAction_Default); // radial->addItem(radId++,0,radId_itemPickup,radAction_Default); } } } } } // mRadialMenu = RadialMenuPtr(radial); // RadialMenuPtr radialPtr(radial); // mRadialMenu = radialPtr; }
void SurveyTool::handleObjectMenuSelect(uint8 messageType,Object* srcObject) { PlayerObject* playerObject = dynamic_cast<PlayerObject*>(srcObject); if( !(playerObject->isConnected()) || playerObject->isDead()) return; // bring up the surve ui switch(messageType) { case radId_itemUse: { //We only need to check this when using the tool's functions! if(playerObject->getPerformingState() != PlayerPerformance_None || playerObject->isDead()) { gMessageLib->SendSystemMessage(::common::OutOfBand("error_message", "survey_cant"), playerObject); return; } // verify we are able to use this if(!(playerObject->verifyAbility(opOCsurvey))) { gMessageLib->SendSystemMessage(::common::OutOfBand("error_message", "insufficient_skill"), playerObject); return; } if(playerObject->getParentId()) { gMessageLib->SendSystemMessage(::common::OutOfBand("error_message", "survey_in_structure"), playerObject); return; } //check whether the tool is initialized already - if not initialize int32 range = getInternalAttribute<int32>("survey_range"); if(range < 0 ) { _createRangeMenu(playerObject, true); return; } StartUsing(playerObject); } break; case radId_serverSurveyToolRange: { if(!(playerObject->verifyAbility(opOCsurvey))) { gMessageLib->SendSystemMessage(::common::OutOfBand("error_message", "insufficient_skill"), playerObject); return; } _createRangeMenu(playerObject); } break; } }
bool ArtisanManager::handleRequestSurvey(Object* playerObject,Object* target,Message* message,ObjectControllerCmdProperties* cmdProperties) { PlayerObject* player = dynamic_cast<PlayerObject*>(playerObject); std::shared_ptr<SimpleEvent> start_survey_event = nullptr; if(cmdProperties) mSurveyMindCost = cmdProperties->mMindCost; // don't allow survey in buildings if(player->getParentId()) { gMessageLib->SendSystemMessage(::common::OutOfBand("error_message", "survey_in_structure"), player); return false; } if(player->getPerformingState() != PlayerPerformance_None) { gMessageLib->SendSystemMessage(::common::OutOfBand("error_message", "wrong_state"), player); return false; } if(player->getSurveyState()) { gMessageLib->SendSystemMessage(::common::OutOfBand("error_message", "survey_cant"), player); return false; } if(player->getSamplingState()) { gMessageLib->SendSystemMessage(::common::OutOfBand("error_message", "survey_sample"), player); return false; } SurveyTool* tool = dynamic_cast<SurveyTool*>(target); CurrentResource* resource = NULL; BString resourceName; message->getStringUnicode16(resourceName); resourceName.convert(BSTRType_ANSI); resource = reinterpret_cast<CurrentResource*>(gResourceManager->getResourceByNameCRC(resourceName.getCrc())); if(tool && resource) { player->setSurveyState(true); // play effect std::string effect = gWorldManager->getClientEffect(tool->getInternalAttribute<uint32>("survey_effect")); gMessageLib->sendPlayClientEffectLocMessage(effect,player->mPosition,player); PlayerObjectSet* playerList = player->getKnownPlayers(); PlayerObjectSet::iterator it = playerList->begin(); while(it != playerList->end()) { gMessageLib->sendPlayClientEffectLocMessage(effect,player->mPosition,(*it)); ++it; } uint32 mindCost = mSurveyMindCost; Ham* hamz = player->getHam(); //are we able to sample in the first place ?? if(!hamz->checkMainPools(0,0,mindCost)) { int32 myMind = hamz->mAction.getCurrentHitPoints(); //return message for sampling cancel based on HAM if(myMind < (int32)mindCost) { gMessageLib->SendSystemMessage(::common::OutOfBand("error_message", "sample_mind"), player); } //message for stop sampling gMessageLib->SendSystemMessage(::common::OutOfBand("survey", "sample_cancel"), player); player->getSampleData()->mPendingSurvey = false; hamz->updateRegenRates(); player->updateMovementProperties(); return false; } hamz->performSpecialAction(0,0,(float)mindCost,HamProperty_CurrentHitpoints); // send system message resourceName.convert(BSTRType_Unicode16); gMessageLib->SendSystemMessage(::common::OutOfBand("survey", "start_survey", L"", L"", resourceName.getUnicode16()), player); // schedule execution start_survey_event = std::make_shared<SimpleEvent>(EventType("start_survey"),0, 5000, std::bind(&ArtisanManager::surveyEvent, this, player, resource, tool)); } else { gMessageLib->SendSystemMessage(::common::OutOfBand("ui","survey_nothingfound")); return false; } // notify any listeners if (start_survey_event) gEventDispatcher.Notify(start_survey_event); return true; }
bool ArtisanManager::handleRequestCoreSample(Object* player,Object* target, Message* message,ObjectControllerCmdProperties* cmdProperties) { PlayerObject* playerObject = dynamic_cast<PlayerObject*>(player); if(cmdProperties) // unfortunately it's not in this opcode // hardcode for now //mSampleActionCost = cmdProperties->mActionCost; mSampleActionCost = 150; if(playerObject->getPerformingState() != PlayerPerformance_None || playerObject->checkIfMounted() || playerObject->isDead()) { gMessageLib->SendSystemMessage(::common::OutOfBand("error_message", "wrong_state"), playerObject); return false; } // can't sample while surveying if(playerObject->getSurveyState()) { gMessageLib->SendSystemMessage(::common::OutOfBand("survey", "sample_survey"), playerObject); return false; } // don't allow sampling in buildings if(playerObject->getParentId()) { gMessageLib->SendSystemMessage(::common::OutOfBand("error_message", "survey_in_structure"), playerObject); return false; } uint64 localTime = Anh_Utils::Clock::getSingleton()->getLocalTime(); // don't allow more than one sample at a time if(playerObject->getSamplingState()) { playerObject->getSampleData()->mPendingSample = false; playerObject->setNextSampleTime(localTime + 18000); gMessageLib->SendSystemMessage(::common::OutOfBand("survey", "tool_recharge_time", 0, 0, 0, (int32)(playerObject->getNextSampleTime() - localTime) / 1000), playerObject); return false; } if(!playerObject->getNextSampleTime() || (int32)(playerObject->getNextSampleTime() - localTime) <= 0) { playerObject->getSampleData()->mPendingSample = false; playerObject->setNextSampleTime(localTime + 18000); } else { gMessageLib->SendSystemMessage(::common::OutOfBand("survey", "tool_recharge_time", 0, 0, 0, (int32)(playerObject->getNextSampleTime() - localTime) / 1000), playerObject); return false; } SurveyTool* tool = dynamic_cast<SurveyTool*>(target); CurrentResource* resource = NULL; BString resourceName; message->getStringUnicode16(resourceName); resourceName.convert(BSTRType_ANSI); resource = reinterpret_cast<CurrentResource*>(gResourceManager->getResourceByNameCRC(resourceName.getCrc())); if(resource == NULL || tool == NULL) { gMessageLib->SendSystemMessage(::common::OutOfBand("ui","survey_noresource"), playerObject); return false; } if((resource->getType()->getCategoryId() == 903)||(resource->getType()->getCategoryId() == 904)) { gMessageLib->SendSystemMessage(::common::OutOfBand("survey", "must_have_harvester"), playerObject); return false; } playerObject->setSamplingState(true); ArtisanHeightmapAsyncContainer* container = new ArtisanHeightmapAsyncContainer(this, HeightmapCallback_ArtisanSurvey); container->addToBatch(playerObject->mPosition.x,playerObject->mPosition.z); container->playerObject = playerObject; container->resource = resource; container->resourceName = resourceName; container->tool = tool; gHeightmap->addNewHeightMapJob(container); return true; }
void ObjectController::handleDataTransform(Message* message,bool inRangeUpdate) { PlayerObject* player = dynamic_cast<PlayerObject*>(mObject); if (!player) { gLogger->logMsgF("ObjectController::handleDataTransform Object is NOT A PLAYER, id = %"PRIu64"", MSG_HIGH, mObject->getId()); return; } glm::vec3 pos; glm::quat dir; uint32 inMoveCount; uint32 tickCount; float speed; bool updateAll = false; // get tick and move counters tickCount = message->getUint32(); inMoveCount = message->getUint32(); // gLogger->logMsg("ObjectController::handleDataTransform"); //uint64 localTimeStart = Anh_Utils::Clock::getSingleton()->getLocalTime(); // only process if its in sequence if(player->getInMoveCount() >= inMoveCount) { return; } //uint32 ticks = tickCount - player->getClientTickCount(); // update tick and move counters... player->setLastMoveTick(tickCount); player->setClientTickCount(tickCount); player->setInMoveCount(inMoveCount); if(player->checkIfMounted() && player->getMount()) { //Player is mounted lets update his mount too player->getMount()->setLastMoveTick(tickCount); //player->getMount()->setInMoveCount((inMoveCount+1)); player->getMount()->setInMoveCount((inMoveCount)); // + 1 or nor does not matter, as long as we update inMoveCount. } // get new direction, position and speed dir.x = message->getFloat(); dir.y = message->getFloat(); dir.z = message->getFloat(); dir.w = message->getFloat(); pos.x = message->getFloat(); pos.y = message->getFloat(); pos.z = message->getFloat(); speed = message->getFloat(); // gLogger->logMsgF("Position outside = %.2f, %.2f, %.2f",MSG_NORMAL, pos.x, pos.y, pos.z); /* if (Heightmap::isHeightmapCacheAvaliable()) { gLogger->logMsgF("Heightmap value = %.2f",MSG_NORMAL, Heightmap::Instance()->getCachedHeightAt2DPosition(pos.x, pos.z)); } */ // gLogger->logMsgF("Direction = %f, %f, %f, %f",MSG_NORMAL, dir.x, dir.y, dir.z, dir.w); // stop entertaining, if we were // important is, that if we move we change our posture to NOT skill animating anymore! // so only stop entertaining when we are performing and NOT skillanimationg if(player->getPerformingState() != PlayerPerformance_None && player->getPosture() != CreaturePosture_SkillAnimating) { gEntertainerManager->stopEntertaining(player); } // if we just left a building if(player->getParentId() != 0) { updateAll = true; // Testing with 4 for add and 0 for remove. // Remove us from previous cell. gMessageLib->broadcastContainmentMessage(player->getId(),player->getParentId(),0,player); // remove us from the last cell we were in if(CellObject* cell = dynamic_cast<CellObject*>(gWorldManager->getObjectById(player->getParentId()))) { cell->removeObject(player); } else { gLogger->logMsgF("Error removing %"PRIu64" from cell(%"PRIu64")",MSG_HIGH,player->getId(),player->getParentId()); } // we are outside again player->setParentId(0); player->mPosition = pos; // Add us to the world. gMessageLib->broadcastContainmentMessage(player->getId(),0,4,player); // add us to the qtree if(QTRegion* newRegion = mSI->getQTRegion((double)pos.x,(double)pos.z)) { player->setSubZoneId((uint32)newRegion->getId()); newRegion->mTree->addObject(player); } else { // we should never get here ! gLogger->logMsg("ObjController::handleDataTransform: could not find zone region in map"); gLogger->logMsg("ObjController:: probably a bot : %i64u",static_cast<int>(player->getId())); // hammertime ! //muglies botter sometimes sends us weird positions //however other 3rd party tools might do the same gWorldManager->addDisconnectedPlayer(player); return; } // Inform tutorial about cell change. if (gWorldConfig->isTutorial()) { player->getTutorial()->setCellId(0); } } else //we are not in a building { // we should be in a qt at this point // get the qt of the new position if(QTRegion* newRegion = mSI->getQTRegion((double)pos.x,(double)pos.z)) { // we didnt change so update the old one if((uint32)newRegion->getId() == player->getSubZoneId()) { // this also updates the players position newRegion->mTree->updateObject(player,pos); //If our player is mounted lets update his mount aswell if(player->checkIfMounted() && player->getMount()) { newRegion->mTree->updateObject(player->getMount(),pos); } } else { updateAll = true; gLogger->logMsg("ObjController::DataTransform: Changing subzone"); // remove from old if(QTRegion* oldRegion = gWorldManager->getQTRegion(player->getSubZoneId())) { oldRegion->mTree->removeObject(player); //If our player is mounted lets update his mount aswell if(player->checkIfMounted() && player->getMount()) { oldRegion->mTree->removeObject(player->getMount()); } } // update players position player->mPosition = pos; //If our player is mounted lets update his mount aswell if(player->checkIfMounted() && player->getMount()) { player->getMount()->mPosition = pos; } // put into new player->setSubZoneId((uint32)newRegion->getId()); newRegion->mTree->addObject(player); //If our player is mounted lets update his mount aswell if(player->checkIfMounted() && player->getMount()) { player->getMount()->setSubZoneId((uint32)newRegion->getId()); newRegion->mTree->addObject(player->getMount()); } } } else { // we should never get here ! gLogger->logMsg("ObjController::DataTransform: could not find zone region in map"); gLogger->logMsg("ObjController:: probably a bot : %I64u",static_cast<int>(player->getId())); // hammertime ! // muglies botter sometimes sends us weird positions with X or Y far out of possible regions // however other 3rd party tools might do the same // we need to get rid of the client at this point nad probably should ban the player / add him to // a monitoring list when the coordinates were indeed out of bounds gWorldManager->addDisconnectedPlayer(player); return; } } player->mDirection = dir; player->setCurrentSpeed(speed); //If our player is mounted lets update his mount aswell if(player->checkIfMounted() && player->getMount()) { player->getMount()->mDirection = dir; player->getMount()->setCurrentSpeed(speed); } // destroy the instanced instrument if out of range if (player->getPlacedInstrumentId()) { if (!gWorldManager->objectsInRange(player->getId(), player->getPlacedInstrumentId(), 5.0)) { if (Item* item = dynamic_cast<Item*>(gWorldManager->getObjectById(player->getPlacedInstrumentId()))) { destroyObject(item->getId()); } } } // Terminate active conversation with npc if to far away (trainers only so far). ActiveConversation* ac = gConversationManager->getActiveConversation(player->getId()); if (ac != NULL) { // We do have a npc conversation going. if (!gWorldManager->objectsInRange(player->getId(), (ac->getNpc())->getId(), 11.0)) { // Terminate conversation, since we are out of range. gMessageLib->sendSystemMessage(player,L"","system_msg","out_of_range"); gConversationManager->stopConversation(player, true); // We will get the current dialog text in a chat bubble, only seen by me. Impressive :) } } if (updateAll) { // Update our world. playerWorldUpdate(true); // Speed up the timed update, if any pending. gWorldManager->addPlayerMovementUpdateTime(player, 250); } else { if (!gWorldConfig->isInstance()) { //If player is mounted... move his mount too! if(player->checkIfMounted() && player->getMount()) { //gMessageLib->sendDataTransform(player->getMount()); gMessageLib->sendUpdateTransformMessage(player->getMount()); } else { // send out position updates to known players // please note that these updates mess up our dance performance if(player->getPerformingState() == PlayerPerformance_None) { gMessageLib->sendUpdateTransformMessage(player); } } } else { // send out position updates to known players in group or self only gMessageLib->sendUpdateTransformMessage(player, player); } } //uint64 localTimeEnd = Anh_Utils::Clock::getSingleton()->getLocalTime(); //gLogger->logMsgF("Exec time PRId32",MSG_NORMAL, localTimeEnd - localTimeStart); }
void ObjectController::handleDataTransformWithParent(Message* message,bool inRangeUpdate) { // FIXME: for now assume we only get messages from players PlayerObject* player = dynamic_cast<PlayerObject*>(mObject); glm::vec3 pos; glm::quat dir; uint32 inMoveCount; uint32 tickCount; uint64 parentId; float speed; bool updateAll = false; // get tick and move counters tickCount = message->getUint32(); inMoveCount = message->getUint32(); // only process if its in sequence if (player->getInMoveCount() <= inMoveCount) { uint64 oldParentId = player->getParentId(); //uint32 ticks = tickCount - player->getClientTickCount(); // update tick and move counters player->setClientTickCount(tickCount); player->setInMoveCount(inMoveCount); // get new direction, position, parent and speed parentId = message->getUint64(); dir.x = message->getFloat(); dir.y = message->getFloat(); dir.z = message->getFloat(); dir.w = message->getFloat(); pos.x = message->getFloat(); pos.y = message->getFloat(); pos.z = message->getFloat(); speed = message->getFloat(); // gLogger->logMsgF("Position inside = %f, %f, %f",MSG_NORMAL, pos.x, pos.y, pos.z); // gLogger->logMsgF("Direction = %f, %f, %f, %f",MSG_NORMAL, dir.x, dir.y, dir.z, dir.w); // stop entertaining, if we were if(player->getPerformingState() != PlayerPerformance_None && player->getPosture() != CreaturePosture_SkillAnimating) { gEntertainerManager->stopEntertaining(player); } // if we changed cell if (oldParentId != parentId) { CellObject* cell = NULL; // gLogger->logMsgF("We changed cell from (%"PRIu64") to (%"PRIu64")",MSG_NORMAL, oldParentId, parentId); // Remove us from whatever we where in before. // (4 for add and 0 for remove) gMessageLib->broadcastContainmentMessage(player->getId(),oldParentId,0,player); // only remove us from si, if we just entered the building if (oldParentId != 0) { if((cell = dynamic_cast<CellObject*>(gWorldManager->getObjectById(oldParentId)))) { cell->removeObject(player); // Done above.. gMessageLib->broadcastContainmentMessage(player->getId(),parentId,4,player); } else { gLogger->logMsgF("Error removing %"PRIu64" from cell(%"PRIu64")",MSG_NORMAL,player->getId(),oldParentId); } } else { updateAll = true; // We just entered the building. // remove us from qt if(player->getSubZoneId()) { if(QTRegion* region = gWorldManager->getQTRegion(player->getSubZoneId())) { player->setSubZoneId(0); region->mTree->removeObject(player); //If our player is mounted lets update his mount aswell if(player->checkIfMounted() && player->getMount()) { player->getMount()->setSubZoneId(0); region->mTree->removeObject(player->getMount()); //Can't ride into a building with a mount! :-p //However, its easy to do so we have handling incase the client is tricked. // the vehicle is the INTANGIBLE Datapad Controller // the *vehicle* itself is the BODY if(Vehicle* datapad_pet = dynamic_cast<Vehicle*>(gWorldManager->getObjectById(player->getMount()->getPetController()))) { datapad_pet->dismountPlayer(); datapad_pet->store(); } } } } } // put us into new one gMessageLib->broadcastContainmentMessage(player->getId(),parentId,4,player); if((cell = dynamic_cast<CellObject*>(gWorldManager->getObjectById(parentId)))) { cell->addObjectSecure(player); // Inform tutorial about cell change. if (gWorldConfig->isTutorial()) { player->getTutorial()->setCellId(parentId); // gLogger->logMsgF("handleDataTransformWithParent: Adding %"PRIu64" to cell(%"PRIu64")",MSG_NORMAL,player->getId(),parentId); } } else { gLogger->logMsgF("Error adding %"PRIu64" to cell(%"PRIu64")",MSG_NORMAL,player->getId(),parentId); } } // update the player player->setParentId(parentId); player->mDirection = dir; player->mPosition = pos; player->setCurrentSpeed(speed); // destroy the instanced instrument if out of range if (player->getPlacedInstrumentId()) { if (!gWorldManager->objectsInRange(player->getId(), player->getPlacedInstrumentId(), 5.0)) { if (Item* item = dynamic_cast<Item*>(gWorldManager->getObjectById(player->getPlacedInstrumentId()))) { destroyObject(item->getId()); } } } // Terminate active conversation with npc if to far away (trainers only so far). ActiveConversation* ac = gConversationManager->getActiveConversation(player->getId()); if (ac != NULL) { // We do have a npc conversation going. if (!gWorldManager->objectsInRange(player->getId(), (ac->getNpc())->getId(), 11.0)) { // Terminate conversation, since we are out of range. gMessageLib->sendSystemMessage(player,L"","system_msg","out_of_range"); gConversationManager->stopConversation(player, true); // We will get the current dialog text in a chat bubble, only seen by me. Impressive :) } } if (updateAll) { // Update our world. playerWorldUpdate(true); // Speed up the timed update, if any pending. gWorldManager->addPlayerMovementUpdateTime(player, 250); } else { if (!gWorldConfig->isInstance()) { // send out updates gMessageLib->sendUpdateTransformMessageWithParent(player); } else { // send out position updates to known players in group or self only gMessageLib->sendUpdateTransformMessageWithParent(player, player); } } } }
void ObjectController::handleDataTransform(Message* message,bool inRangeUpdate) { PlayerObject* player = dynamic_cast<PlayerObject*>(mObject); if (!player) { return; } glm::vec3 pos; glm::quat dir; uint32 inMoveCount; uint32 tickCount; float speed; bool updateAll = false; // get tick and move counters tickCount = message->getUint32(); inMoveCount = message->getUint32(); // only process if its in sequence if(player->getInMoveCount() >= inMoveCount) { return; } //uint32 ticks = tickCount - player->getClientTickCount(); // update tick and move counters... player->setLastMoveTick(tickCount); player->setClientTickCount(tickCount); player->setInMoveCount(inMoveCount); // get new direction, position and speed dir.x = message->getFloat(); dir.y = message->getFloat(); dir.z = message->getFloat(); dir.w = message->getFloat(); pos.x = message->getFloat(); pos.y = message->getFloat(); pos.z = message->getFloat(); speed = message->getFloat(); // stop entertaining ??? // important is, that if we move we change our posture to NOT skill animating anymore! // so only stop entertaining when we are performing and NOT skillanimationg if(player->getPerformingState() != PlayerPerformance_None && player->states.getPosture() != CreaturePosture_SkillAnimating) { gEntertainerManager->stopEntertaining(player); } // if we just left a building if(player->getParentId() != 0) { updateAll = true; // Testing with 4 for add and 0 for remove. // Remove us from previous cell. gMessageLib->broadcastContainmentMessage(player->getId(),player->getParentId(),0,player); // remove us from the last cell we were in if(CellObject* cell = dynamic_cast<CellObject*>(gWorldManager->getObjectById(player->getParentId()))) { cell->removeObject(player); } else { DLOG(INFO) << "Error removing" << player->getId() << " from cell " << player->getParentId(); } // we are outside again player->setParentId(0); player->mPosition = pos; // Add us to the world. gMessageLib->broadcastContainmentMessage(player->getId(),0,4,player); // add us to the qtree if(QTRegion* newRegion = mSI->getQTRegion((double)pos.x,(double)pos.z)) { player->setSubZoneId((uint32)newRegion->getId()); player->setSubZone(newRegion); newRegion->mTree->addObject(player); } else { // we should never get here ! // it basically means we left the map DLOG(INFO) << "ObjController::handleDataTransform: could not find zone region in map"; DLOG(INFO) << "ObjController:: probably a bot : " << player->getId(); // hammertime ! //muglies botter sometimes sends us weird positions //however other 3rd party tools might do the same gWorldManager->addDisconnectedPlayer(player); return; } // Inform tutorial about cell change. if (gWorldConfig->isTutorial()) { player->getTutorial()->setCellId(0); } } else //we are not in a building { // we should be in a qt at this point check our qt if we still are inside its bounds // please note, that there is exactly *one* qtregion per planet and qtregions do *not* overlap // so there is no need to search the region everytime even if we should decide to add more qtregions // subzone is NULL however, when we just left a building if(player->getSubZone() && player->getSubZone()->checkPlayerPosition(pos.x, pos.z)) { // this also updates the players position player->getSubZone()->mTree->updateObject(player,pos); //If our player is mounted lets update his mount aswell if(player->checkIfMounted() && player->getMount()) { player->getSubZone()->mTree->updateObject(player->getMount(),pos); } } else //do an intersectsWithQuery of objects in the si to find our new region - //CAVE shouldnt it be a contains query ? //what do we do if several regions overlap ? if(QTRegion* newRegion = mSI->getQTRegion((double)pos.x,(double)pos.z)) { updateAll = true; // remove from old if(QTRegion* oldRegion = player->getSubZone()) { oldRegion->mTree->removeObject(player); //If our player is mounted lets update his mount aswell if(player->checkIfMounted() && player->getMount()) { oldRegion->mTree->removeObject(player->getMount()); } } // update players position player->mPosition = pos; //If our player is mounted lets update his mount aswell if(player->checkIfMounted() && player->getMount()) { player->getMount()->mPosition = pos; } // put into new player->setSubZoneId((uint32)newRegion->getId()); player->setSubZone(newRegion); newRegion->mTree->addObject(player); //If our player is mounted lets update his mount aswell if(player->checkIfMounted() && player->getMount()) { player->getMount()->setSubZoneId((uint32)newRegion->getId()); newRegion->mTree->addObject(player->getMount()); } } else { // we should never get here ! DLOG(INFO) << "ObjController::handleDataTransform: could not find zone region in map"; DLOG(INFO) << "ObjController:: probably a bot : " << player->getId(); // hammertime ! // muglies botter sometimes sends us weird positions with X or Y far out of possible regions // however other 3rd party tools might do the same // we need to get rid of the client at this point nad probably should ban the player / add him to // a monitoring list when the coordinates were indeed out of bounds gWorldManager->addDisconnectedPlayer(player); return; } } player->mDirection = dir; player->setCurrentSpeed(speed); // destroy the instanced instrument if out of range if (player->getPlacedInstrumentId()) { if (!gWorldManager->objectsInRange(player->getId(), player->getPlacedInstrumentId(), 5.0)) { if (Item* item = dynamic_cast<Item*>(gWorldManager->getObjectById(player->getPlacedInstrumentId()))) { destroyObject(item->getId()); } } } // Terminate active conversation with npc if to far away (trainers only so far). ActiveConversation* ac = gConversationManager->getActiveConversation(player->getId()); if (ac != NULL) { // We do have a npc conversation going. if (!gWorldManager->objectsInRange(player->getId(), (ac->getNpc())->getId(), 11.0)) { // Terminate conversation, since we are out of range. gMessageLib->SendSystemMessage(::common::OutOfBand("system_msg", "out_of_range"), player); gConversationManager->stopConversation(player, true); // We will get the current dialog text in a chat bubble, only seen by me. Impressive :) } } if (updateAll) { // Update our world. playerWorldUpdate(true); // Speed up the timed update, if any pending. gWorldManager->addPlayerMovementUpdateTime(player, 250); } else { if (!gWorldConfig->isInstance()) { //If player is mounted... move his mount too! if(player->checkIfMounted() && player->getMount()) { //gMessageLib->sendDataTransform(player->getMount()); player->getMount()->mDirection = dir; player->getMount()->setCurrentSpeed(speed); player->getMount()->setLastMoveTick(tickCount); player->getMount()->setInMoveCount((inMoveCount)); // + 1 or nor does not matter, as long as we update inMoveCount. gMessageLib->sendUpdateTransformMessage(player->getMount()); } else { // send out position updates to known players // please note that these updates mess up our dance performance /*if(player->getPerformingState() == PlayerPerformance_None) {*/ gMessageLib->sendUpdateTransformMessage(player); //} } } else { // send out position updates to known players in group or self only gMessageLib->sendUpdateTransformMessage(player, player); } } }