void ObjectController::_handleTeach(uint64 targetId,Message* message,ObjectControllerCmdProperties* cmdProperties) { // check if our attribute targetplayer exists // check if our target is a player // parse the string if a known skill was selected // check what skills we can teach // check which of these skills the target might learn PlayerObject* teacherObject = dynamic_cast<PlayerObject*>(mObject); PlayerObject* pupilObject = dynamic_cast<PlayerObject*> (teacherObject->getTarget()); // check if we have a target if(!pupilObject ) { gMessageLib->sendSystemMessage(teacherObject,L"","teaching","no_target"); return; } if(pupilObject == teacherObject) { // target self:( gMessageLib->sendSystemMessage(teacherObject,L"","teaching","no_teach_self"); return; } if((teacherObject->getGroupId() == 0)||(teacherObject->getGroupId() != pupilObject ->getGroupId())) { gMessageLib->sendSystemMessage(teacherObject,L"","teaching","not_in_same_group","","",L"",0,"","",L"",pupilObject->getId()); return; } //check if our pupil already gets taught if (!pupilObject->getTrade()->getTeacher()) { pupilObject->getTrade()->setTeacher(teacherObject); gSkillManager->teach(pupilObject,teacherObject,""); } else { gMessageLib->sendSystemMessage(teacherObject,L"","teaching","student_has_offer_to_learn","","",L"",0,"","",L"",pupilObject->getId()); } }
uint64 ObjectController::playerWorldUpdate(bool forcedUpdate) { PlayerObject* player = dynamic_cast<PlayerObject*>(mObject); // If we already are busy, don't start another update. // ie if this is called by the worldmanager timer because we still have unupdated objects // in our resultmap if (!(mUpdatingObjects || mDestroyOutOfRangeObjects || forcedUpdate)) { // If we have been inactive for too long, let's update the world. if (player->getCurrentSpeed() == 0.0) { //is this the amount of full updates already running ? if (++mFullUpdateTrigger >= 15) // We only check this when we are running idle with low frequency { // gLogger->logMsg("... sitting still to long!"); // Let's update the world forcedUpdate = true; mFullUpdateTrigger = 0; } } else { mFullUpdateTrigger = 0; } } // Are we inside or outside? if (player->getParentId() != 0) { // We are inside. if (mUpdatingObjects || forcedUpdate) { // Just entered the building? // if (!mUpdatingObjects) // We need to abort any pending operation if we get a forcedUpdate (meaning entered, changed or left a cell or subzone). if (forcedUpdate) { // Update all. // gLogger->logMsg("ObjController::handleDataTransformWithParent: _findInRangeObjectsInside(true)"); _findInRangeObjectsInside(true); } } else { // This is the faster update, stil based on SI though. _findInRangeObjectsInside(false); } // Update some of the objects we found. mUpdatingObjects = !_updateInRangeObjectsInside(); } else { // We are outside. bool OutOfUpdateRange = false; // If we "just stopped" and not busy with updating, make a full update. if (!mUpdatingObjects && !mDestroyOutOfRangeObjects) { // We are not "busy" processing anything from previous sessions. if (player->getCurrentSpeed() == 0.0) { if (mMovementInactivityTrigger > 0) { if (--mMovementInactivityTrigger == 0) { // gLogger->logMsg("We are not moving..."); // We are not moving, but how far are we from last full update pos? if (glm::distance(player->mPosition, player->getLastUpdatePosition()) < 16) { // Force a full update, inclusive of saving current "update pos". // gLogger->logMsg("... forced update!"); OutOfUpdateRange = true; } else { // gLogger->logMsgF("... but to close to last update pos, %.1f",MSG_NORMAL, player->mPosition.distance2D(player->getLastUpdatePosition())); } } } } else { mMovementInactivityTrigger = 2; // We only check this when we are running idle with slow frequency // Need to be standstill for this amount of seconds * 5 (or whatever time we use for slow updates) before we update. } } // Position check for SI-update. OutOfUpdateRange |= !(glm::distance(player->mPosition, player->getLastUpdatePosition()) < 64.0f); //OutOfUpdateRange |= !(player->mPosition.inRange2D(player->getLastUpdatePosition(),64.0f)); // gLogger->logMsgF("Distance = %f",MSG_NORMAL, player->mPosition.distance2D(player->getLastUpdatePosition())); if (mUpdatingObjects || forcedUpdate || OutOfUpdateRange) { // More than 64 m from where we loaded SI, reload it. // We need to abort any pending operation if we get a forcedUpdate (meaning entered, changed or left a cell or subzone). if ((forcedUpdate) || OutOfUpdateRange) { // Save these coordinates // gLogger->logMsg("forcedUpdate"); mDestroyOutOfRangeObjects = false; // Stop the destroy-messages, in case we already have started to send them. if (OutOfUpdateRange) { // gLogger->logMsg("Out of 64m range"); player->setLastUpdatePosition(player->mPosition); //If our player is mounted let's update his mount if(player->checkIfMounted() && player->getMount()) { player->getMount()->setLastUpdatePosition(player->mPosition); } // We shall destroy out of range objects when we are done with the update of known objects. mDestroyOutOfRangeObjects = true; } _findInRangeObjectsOutside(true); } } else if (!mDestroyOutOfRangeObjects) { // This is the fast update, based on qt. // gLogger->logMsg("_findInRangeObjectsOutside(false)"); _findInRangeObjectsOutside(false); } // Update some of the objects we found. mUpdatingObjects = !_updateInRangeObjectsOutside(); if (!mUpdatingObjects) { // We are not updating new objects. if (mDestroyOutOfRangeObjects) { // We are ready to destroy objects out of range. if (_destroyOutOfRangeObjects(&mInRangeObjects)) { // All objects are now destroyed. mDestroyOutOfRangeObjects = false; // If active target out of range, clear. if (player->getTarget()) { // gLogger->logMsgF("playerWorldUpdate have a Target of type %d", MSG_NORMAL, player->getTarget()->getType()); // The list of objects we shall check for untargeting consist of all objects that we can "interact with". if ((player->getTarget()->getType() & (ObjType_Player | ObjType_NPC | ObjType_Creature)) || ((player->getTarget()->getType() == ObjType_Tangible) && (dynamic_cast<TangibleObject*>(player->getTarget())->getTangibleGroup() == TanGroup_TicketCollector))) { if (!(player->checkKnownObjects(player->getTarget()))) { player->setTarget(NULL); gMessageLib->sendTargetUpdateDeltasCreo6(player); // gLogger->logMsg("playerWorldUpdate clear Target"); } } } } } } } uint64 msToWait = 4900; // Will give 5 sec. if (mUpdatingObjects || mDestroyOutOfRangeObjects) { // We are busy, need to continue processing asap. msToWait = 900; // This should make us tick every second, since that's the base time for the timer we use. } return msToWait; }