/indra/newview/llagent.cpp
C++ | 2290 lines | 1520 code | 359 blank | 411 comment | 278 complexity | bfe4cf9f8dd32ace522c7ee9a89474c4 MD5 | raw file
Possible License(s): LGPL-2.1
- /**
- * @file llagent.cpp
- * @brief LLAgent class implementation
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
- #include "llviewerprecompiledheaders.h"
- #include "llagent.h"
- #include "pipeline.h"
- #include "llagentaccess.h"
- #include "llagentcamera.h"
- #include "llagentlistener.h"
- #include "llagentwearables.h"
- #include "llagentui.h"
- #include "llanimationstates.h"
- #include "llcallingcard.h"
- #include "llcapabilitylistener.h"
- #include "llchannelmanager.h"
- #include "llchicletbar.h"
- #include "llconsole.h"
- #include "llenvmanager.h"
- #include "llfirstuse.h"
- #include "llfloatercamera.h"
- #include "llfloaterreg.h"
- #include "llfloatertools.h"
- #include "llgroupactions.h"
- #include "llgroupmgr.h"
- #include "llhomelocationresponder.h"
- #include "llhudmanager.h"
- #include "lljoystickbutton.h"
- #include "llmorphview.h"
- #include "llmoveview.h"
- #include "llnavigationbar.h" // to show/hide navigation bar when changing mouse look state
- #include "llnearbychatbar.h"
- #include "llnotificationsutil.h"
- #include "llpaneltopinfobar.h"
- #include "llparcel.h"
- #include "llrendersphere.h"
- #include "llsdmessage.h"
- #include "llsdutil.h"
- #include "llsky.h"
- #include "llslurl.h"
- #include "llsmoothstep.h"
- #include "llstartup.h"
- #include "llstatusbar.h"
- #include "llteleportflags.h"
- #include "lltool.h"
- #include "lltoolbarview.h"
- #include "lltoolpie.h"
- #include "lltoolmgr.h"
- #include "lltrans.h"
- #include "lluictrl.h"
- #include "llurlentry.h"
- #include "llviewercontrol.h"
- #include "llviewerdisplay.h"
- #include "llviewerjoystick.h"
- #include "llviewermediafocus.h"
- #include "llviewermenu.h"
- #include "llviewerobjectlist.h"
- #include "llviewerparcelmgr.h"
- #include "llviewerstats.h"
- #include "llviewerwindow.h"
- #include "llvoavatarself.h"
- #include "llwindow.h"
- #include "llworld.h"
- #include "llworldmap.h"
- #include "stringize.h"
- using namespace LLVOAvatarDefines;
- extern LLMenuBarGL* gMenuBarView;
- const BOOL ANIMATE = TRUE;
- const U8 AGENT_STATE_TYPING = 0x04;
- const U8 AGENT_STATE_EDITING = 0x10;
- // Autopilot constants
- const F32 AUTOPILOT_HEIGHT_ADJUST_DISTANCE = 8.f; // meters
- const F32 AUTOPILOT_MIN_TARGET_HEIGHT_OFF_GROUND = 1.f; // meters
- const F32 AUTOPILOT_MAX_TIME_NO_PROGRESS = 1.5f; // seconds
- const F32 MAX_VELOCITY_AUTO_LAND_SQUARED = 4.f * 4.f;
- const F64 CHAT_AGE_FAST_RATE = 3.0;
- // fidget constants
- const F32 MIN_FIDGET_TIME = 8.f; // seconds
- const F32 MAX_FIDGET_TIME = 20.f; // seconds
- // The agent instance.
- LLAgent gAgent;
- //--------------------------------------------------------------------
- // Statics
- //
- /// minimum time after setting away state before coming back based on movement
- const F32 LLAgent::MIN_AFK_TIME = 10.0f;
- const F32 LLAgent::TYPING_TIMEOUT_SECS = 5.f;
- std::map<std::string, std::string> LLAgent::sTeleportErrorMessages;
- std::map<std::string, std::string> LLAgent::sTeleportProgressMessages;
- class LLAgentFriendObserver : public LLFriendObserver
- {
- public:
- LLAgentFriendObserver() {}
- virtual ~LLAgentFriendObserver() {}
- virtual void changed(U32 mask);
- };
- void LLAgentFriendObserver::changed(U32 mask)
- {
- // if there's a change we're interested in.
- if((mask & (LLFriendObserver::POWERS)) != 0)
- {
- gAgent.friendsChanged();
- }
- }
- bool handleSlowMotionAnimation(const LLSD& newvalue)
- {
- if (newvalue.asBoolean())
- {
- gAgentAvatarp->setAnimTimeFactor(0.2f);
- }
- else
- {
- gAgentAvatarp->setAnimTimeFactor(1.0f);
- }
- return true;
- }
- // static
- void LLAgent::parcelChangedCallback()
- {
- bool can_edit = LLToolMgr::getInstance()->canEdit();
- gAgent.mCanEditParcel = can_edit;
- }
- // static
- bool LLAgent::isActionAllowed(const LLSD& sdname)
- {
- bool retval = false;
- const std::string& param = sdname.asString();
- if (param == "build")
- {
- retval = gAgent.canEditParcel();
- }
- else if (param == "speak")
- {
- if ( gAgent.isVoiceConnected() &&
- LLViewerParcelMgr::getInstance()->allowAgentVoice() &&
- ! LLVoiceClient::getInstance()->inTuningMode() )
- {
- retval = true;
- }
- else
- {
- retval = false;
- }
- }
- return retval;
- }
- // static
- void LLAgent::pressMicrophone(const LLSD& name)
- {
- LLFirstUse::speak(false);
- LLVoiceClient::getInstance()->inputUserControlState(true);
- }
- // static
- void LLAgent::releaseMicrophone(const LLSD& name)
- {
- LLVoiceClient::getInstance()->inputUserControlState(false);
- }
- // static
- void LLAgent::toggleMicrophone(const LLSD& name)
- {
- LLVoiceClient::getInstance()->toggleUserPTTState();
- }
- // static
- bool LLAgent::isMicrophoneOn(const LLSD& sdname)
- {
- return LLVoiceClient::getInstance()->getUserPTTState();
- }
- // ************************************************************
- // Enabled this definition to compile a 'hacked' viewer that
- // locally believes the end user has godlike powers.
- // #define HACKED_GODLIKE_VIEWER
- // For a toggled version, see viewer.h for the
- // TOGGLE_HACKED_GODLIKE_VIEWER define, instead.
- // ************************************************************
- // Constructors and Destructors
- // JC - Please try to make this order match the order in the header
- // file. Otherwise it's hard to find variables that aren't initialized.
- //-----------------------------------------------------------------------------
- // LLAgent()
- //-----------------------------------------------------------------------------
- LLAgent::LLAgent() :
- mGroupPowers(0),
- mHideGroupTitle(FALSE),
- mGroupID(),
- mInitialized(FALSE),
- mListener(),
- mDoubleTapRunTimer(),
- mDoubleTapRunMode(DOUBLETAP_NONE),
- mbAlwaysRun(false),
- mbRunning(false),
- mbTeleportKeepsLookAt(false),
- mAgentAccess(new LLAgentAccess(gSavedSettings)),
- mCanEditParcel(false),
- mTeleportSourceSLURL(new LLSLURL),
- mTeleportState( TELEPORT_NONE ),
- mRegionp(NULL),
- mAgentOriginGlobal(),
- mPositionGlobal(),
- mDistanceTraveled(0.F),
- mLastPositionGlobal(LLVector3d::zero),
- mRenderState(0),
- mTypingTimer(),
- mViewsPushed(FALSE),
- mCustomAnim(FALSE),
- mShowAvatar(TRUE),
- mFrameAgent(),
- mIsBusy(FALSE),
- mControlFlags(0x00000000),
- mbFlagsDirty(FALSE),
- mbFlagsNeedReset(FALSE),
- mAutoPilot(FALSE),
- mAutoPilotFlyOnStop(FALSE),
- mAutoPilotAllowFlying(TRUE),
- mAutoPilotTargetGlobal(),
- mAutoPilotStopDistance(1.f),
- mAutoPilotUseRotation(FALSE),
- mAutoPilotTargetFacing(LLVector3::zero),
- mAutoPilotTargetDist(0.f),
- mAutoPilotNoProgressFrameCount(0),
- mAutoPilotRotationThreshold(0.f),
- mAutoPilotFinishedCallback(NULL),
- mAutoPilotCallbackData(NULL),
-
- mEffectColor(new LLUIColor(LLColor4(0.f, 1.f, 1.f, 1.f))),
- mHaveHomePosition(FALSE),
- mHomeRegionHandle( 0 ),
- mNearChatRadius(CHAT_NORMAL_RADIUS / 2.f),
- mNextFidgetTime(0.f),
- mCurrentFidget(0),
- mFirstLogin(FALSE),
- mGenderChosen(FALSE),
-
- mVoiceConnected(false),
- mAppearanceSerialNum(0),
- mMouselookModeInSignal(NULL),
- mMouselookModeOutSignal(NULL)
- {
- for (U32 i = 0; i < TOTAL_CONTROLS; i++)
- {
- mControlsTakenCount[i] = 0;
- mControlsTakenPassedOnCount[i] = 0;
- }
- mListener.reset(new LLAgentListener(*this));
- mMoveTimer.stop();
- }
- // Requires gSavedSettings to be initialized.
- //-----------------------------------------------------------------------------
- // init()
- //-----------------------------------------------------------------------------
- void LLAgent::init()
- {
- mMoveTimer.start();
- gSavedSettings.declareBOOL("SlowMotionAnimation", FALSE, "Declared in code", FALSE);
- gSavedSettings.getControl("SlowMotionAnimation")->getSignal()->connect(boost::bind(&handleSlowMotionAnimation, _2));
-
- // *Note: this is where LLViewerCamera::getInstance() used to be constructed.
- setFlying( gSavedSettings.getBOOL("FlyingAtExit") );
- *mEffectColor = LLUIColorTable::instance().getColor("EffectColor");
- gSavedSettings.getControl("PreferredMaturity")->getValidateSignal()->connect(boost::bind(&LLAgent::validateMaturity, this, _2));
- gSavedSettings.getControl("PreferredMaturity")->getSignal()->connect(boost::bind(&LLAgent::handleMaturity, this, _2));
- LLViewerParcelMgr::getInstance()->addAgentParcelChangedCallback(boost::bind(&LLAgent::parcelChangedCallback));
- mInitialized = TRUE;
- }
- //-----------------------------------------------------------------------------
- // cleanup()
- //-----------------------------------------------------------------------------
- void LLAgent::cleanup()
- {
- mRegionp = NULL;
- }
- //-----------------------------------------------------------------------------
- // LLAgent()
- //-----------------------------------------------------------------------------
- LLAgent::~LLAgent()
- {
- cleanup();
- delete mMouselookModeInSignal;
- mMouselookModeInSignal = NULL;
- delete mMouselookModeOutSignal;
- mMouselookModeOutSignal = NULL;
- delete mAgentAccess;
- mAgentAccess = NULL;
- delete mEffectColor;
- mEffectColor = NULL;
- delete mTeleportSourceSLURL;
- mTeleportSourceSLURL = NULL;
- }
- // Handle any actions that need to be performed when the main app gains focus
- // (such as through alt-tab).
- //-----------------------------------------------------------------------------
- // onAppFocusGained()
- //-----------------------------------------------------------------------------
- void LLAgent::onAppFocusGained()
- {
- if (CAMERA_MODE_MOUSELOOK == gAgentCamera.getCameraMode())
- {
- gAgentCamera.changeCameraToDefault();
- LLToolMgr::getInstance()->clearSavedTool();
- }
- }
- void LLAgent::ageChat()
- {
- if (isAgentAvatarValid())
- {
- // get amount of time since I last chatted
- F64 elapsed_time = (F64)gAgentAvatarp->mChatTimer.getElapsedTimeF32();
- // add in frame time * 3 (so it ages 4x)
- gAgentAvatarp->mChatTimer.setAge(elapsed_time + (F64)gFrameDTClamped * (CHAT_AGE_FAST_RATE - 1.0));
- }
- }
- //-----------------------------------------------------------------------------
- // moveAt()
- //-----------------------------------------------------------------------------
- void LLAgent::moveAt(S32 direction, bool reset)
- {
- mMoveTimer.reset();
- LLFirstUse::notMoving(false);
- // age chat timer so it fades more quickly when you are intentionally moving
- ageChat();
- gAgentCamera.setAtKey(LLAgentCamera::directionToKey(direction));
- if (direction > 0)
- {
- setControlFlags(AGENT_CONTROL_AT_POS | AGENT_CONTROL_FAST_AT);
- }
- else if (direction < 0)
- {
- setControlFlags(AGENT_CONTROL_AT_NEG | AGENT_CONTROL_FAST_AT);
- }
- if (reset)
- {
- gAgentCamera.resetView();
- }
- }
- //-----------------------------------------------------------------------------
- // moveAtNudge()
- //-----------------------------------------------------------------------------
- void LLAgent::moveAtNudge(S32 direction)
- {
- mMoveTimer.reset();
- LLFirstUse::notMoving(false);
- // age chat timer so it fades more quickly when you are intentionally moving
- ageChat();
- gAgentCamera.setWalkKey(LLAgentCamera::directionToKey(direction));
- if (direction > 0)
- {
- setControlFlags(AGENT_CONTROL_NUDGE_AT_POS);
- }
- else if (direction < 0)
- {
- setControlFlags(AGENT_CONTROL_NUDGE_AT_NEG);
- }
- gAgentCamera.resetView();
- }
- //-----------------------------------------------------------------------------
- // moveLeft()
- //-----------------------------------------------------------------------------
- void LLAgent::moveLeft(S32 direction)
- {
- mMoveTimer.reset();
- LLFirstUse::notMoving(false);
- // age chat timer so it fades more quickly when you are intentionally moving
- ageChat();
- gAgentCamera.setLeftKey(LLAgentCamera::directionToKey(direction));
- if (direction > 0)
- {
- setControlFlags(AGENT_CONTROL_LEFT_POS | AGENT_CONTROL_FAST_LEFT);
- }
- else if (direction < 0)
- {
- setControlFlags(AGENT_CONTROL_LEFT_NEG | AGENT_CONTROL_FAST_LEFT);
- }
- gAgentCamera.resetView();
- }
- //-----------------------------------------------------------------------------
- // moveLeftNudge()
- //-----------------------------------------------------------------------------
- void LLAgent::moveLeftNudge(S32 direction)
- {
- mMoveTimer.reset();
- LLFirstUse::notMoving(false);
- // age chat timer so it fades more quickly when you are intentionally moving
- ageChat();
- gAgentCamera.setLeftKey(LLAgentCamera::directionToKey(direction));
- if (direction > 0)
- {
- setControlFlags(AGENT_CONTROL_NUDGE_LEFT_POS);
- }
- else if (direction < 0)
- {
- setControlFlags(AGENT_CONTROL_NUDGE_LEFT_NEG);
- }
- gAgentCamera.resetView();
- }
- //-----------------------------------------------------------------------------
- // moveUp()
- //-----------------------------------------------------------------------------
- void LLAgent::moveUp(S32 direction)
- {
- mMoveTimer.reset();
- LLFirstUse::notMoving(false);
- // age chat timer so it fades more quickly when you are intentionally moving
- ageChat();
- gAgentCamera.setUpKey(LLAgentCamera::directionToKey(direction));
- if (direction > 0)
- {
- setControlFlags(AGENT_CONTROL_UP_POS | AGENT_CONTROL_FAST_UP);
- }
- else if (direction < 0)
- {
- setControlFlags(AGENT_CONTROL_UP_NEG | AGENT_CONTROL_FAST_UP);
- }
- gAgentCamera.resetView();
- }
- //-----------------------------------------------------------------------------
- // moveYaw()
- //-----------------------------------------------------------------------------
- void LLAgent::moveYaw(F32 mag, bool reset_view)
- {
- gAgentCamera.setYawKey(mag);
- if (mag > 0)
- {
- setControlFlags(AGENT_CONTROL_YAW_POS);
- }
- else if (mag < 0)
- {
- setControlFlags(AGENT_CONTROL_YAW_NEG);
- }
- if (reset_view)
- {
- gAgentCamera.resetView();
- }
- }
- //-----------------------------------------------------------------------------
- // movePitch()
- //-----------------------------------------------------------------------------
- void LLAgent::movePitch(F32 mag)
- {
- gAgentCamera.setPitchKey(mag);
- if (mag > 0)
- {
- setControlFlags(AGENT_CONTROL_PITCH_POS);
- }
- else if (mag < 0)
- {
- setControlFlags(AGENT_CONTROL_PITCH_NEG);
- }
- }
- // Does this parcel allow you to fly?
- BOOL LLAgent::canFly()
- {
- if (isGodlike()) return TRUE;
- LLViewerRegion* regionp = getRegion();
- if (regionp && regionp->getBlockFly()) return FALSE;
-
- LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
- if (!parcel) return FALSE;
- // Allow owners to fly on their own land.
- if (LLViewerParcelMgr::isParcelOwnedByAgent(parcel, GP_LAND_ALLOW_FLY))
- {
- return TRUE;
- }
- return parcel->getAllowFly();
- }
- BOOL LLAgent::getFlying() const
- {
- return mControlFlags & AGENT_CONTROL_FLY;
- }
- //-----------------------------------------------------------------------------
- // setFlying()
- //-----------------------------------------------------------------------------
- void LLAgent::setFlying(BOOL fly)
- {
- if (isAgentAvatarValid())
- {
- // *HACK: Don't allow to start the flying mode if we got ANIM_AGENT_STANDUP signal
- // because in this case we won't get a signal to start avatar flying animation and
- // it will be walking with flying mode "ON" indication. However we allow to switch
- // the flying mode off if we get ANIM_AGENT_STANDUP signal. See process_avatar_animation().
- // See EXT-2781.
- if(fly && gAgentAvatarp->mSignaledAnimations.find(ANIM_AGENT_STANDUP) != gAgentAvatarp->mSignaledAnimations.end())
- {
- return;
- }
- // don't allow taking off while sitting
- if (fly && gAgentAvatarp->isSitting())
- {
- return;
- }
- }
- if (fly)
- {
- BOOL was_flying = getFlying();
- if (!canFly() && !was_flying)
- {
- // parcel doesn't let you start fly
- // gods can always fly
- // and it's OK if you're already flying
- make_ui_sound("UISndBadKeystroke");
- return;
- }
- if( !was_flying )
- {
- LLViewerStats::getInstance()->incStat(LLViewerStats::ST_FLY_COUNT);
- }
- setControlFlags(AGENT_CONTROL_FLY);
- }
- else
- {
- clearControlFlags(AGENT_CONTROL_FLY);
- }
- // Update Movement Controls according to Fly mode
- LLFloaterMove::setFlyingMode(fly);
- mbFlagsDirty = TRUE;
- }
- // UI based mechanism of setting fly state
- //-----------------------------------------------------------------------------
- // toggleFlying()
- //-----------------------------------------------------------------------------
- // static
- void LLAgent::toggleFlying()
- {
- if ( gAgent.mAutoPilot )
- {
- LLToolPie::instance().stopClickToWalk();
- }
- BOOL fly = !gAgent.getFlying();
- gAgent.mMoveTimer.reset();
- LLFirstUse::notMoving(false);
- gAgent.setFlying( fly );
- gAgentCamera.resetView();
- }
- // static
- bool LLAgent::enableFlying()
- {
- BOOL sitting = FALSE;
- if (isAgentAvatarValid())
- {
- sitting = gAgentAvatarp->isSitting();
- }
- return !sitting;
- }
- void LLAgent::standUp()
- {
- setControlFlags(AGENT_CONTROL_STAND_UP);
- }
- //-----------------------------------------------------------------------------
- // setRegion()
- //-----------------------------------------------------------------------------
- void LLAgent::setRegion(LLViewerRegion *regionp)
- {
- bool teleport = true;
- llassert(regionp);
- if (mRegionp != regionp)
- {
- // std::string host_name;
- // host_name = regionp->getHost().getHostName();
- std::string ip = regionp->getHost().getString();
- llinfos << "Moving agent into region: " << regionp->getName()
- << " located at " << ip << llendl;
- if (mRegionp)
- {
- // We've changed regions, we're now going to change our agent coordinate frame.
- mAgentOriginGlobal = regionp->getOriginGlobal();
- LLVector3d agent_offset_global = mRegionp->getOriginGlobal();
- LLVector3 delta;
- delta.setVec(regionp->getOriginGlobal() - mRegionp->getOriginGlobal());
- setPositionAgent(getPositionAgent() - delta);
- LLVector3 camera_position_agent = LLViewerCamera::getInstance()->getOrigin();
- LLViewerCamera::getInstance()->setOrigin(camera_position_agent - delta);
- // Update all of the regions.
- LLWorld::getInstance()->updateAgentOffset(agent_offset_global);
- // Hack to keep sky in the agent's region, otherwise it may get deleted - DJS 08/02/02
- // *TODO: possibly refactor into gSky->setAgentRegion(regionp)? -Brad
- if (gSky.mVOSkyp)
- {
- gSky.mVOSkyp->setRegion(regionp);
- }
- if (gSky.mVOGroundp)
- {
- gSky.mVOGroundp->setRegion(regionp);
- }
- // Notify windlight managers
- teleport = (gAgent.getTeleportState() != LLAgent::TELEPORT_NONE);
- }
- else
- {
- // First time initialization.
- // We've changed regions, we're now going to change our agent coordinate frame.
- mAgentOriginGlobal = regionp->getOriginGlobal();
- LLVector3 delta;
- delta.setVec(regionp->getOriginGlobal());
- setPositionAgent(getPositionAgent() - delta);
- LLVector3 camera_position_agent = LLViewerCamera::getInstance()->getOrigin();
- LLViewerCamera::getInstance()->setOrigin(camera_position_agent - delta);
- // Update all of the regions.
- LLWorld::getInstance()->updateAgentOffset(mAgentOriginGlobal);
- }
- // Pass new region along to metrics components that care about this level of detail.
- LLAppViewer::metricsUpdateRegion(regionp->getHandle());
- }
- mRegionp = regionp;
- // Pass the region host to LLUrlEntryParcel to resolve parcel name
- // with a server request.
- LLUrlEntryParcel::setRegionHost(getRegionHost());
- // Must shift hole-covering water object locations because local
- // coordinate frame changed.
- LLWorld::getInstance()->updateWaterObjects();
- // keep a list of regions we've been too
- // this is just an interesting stat, logged at the dataserver
- // we could trake this at the dataserver side, but that's harder
- U64 handle = regionp->getHandle();
- mRegionsVisited.insert(handle);
- LLSelectMgr::getInstance()->updateSelectionCenter();
- LLFloaterMove::sUpdateFlyingStatus();
- if (teleport)
- {
- LLEnvManagerNew::instance().onTeleport();
- }
- else
- {
- LLEnvManagerNew::instance().onRegionCrossing();
- }
- }
- //-----------------------------------------------------------------------------
- // getRegion()
- //-----------------------------------------------------------------------------
- LLViewerRegion *LLAgent::getRegion() const
- {
- return mRegionp;
- }
- LLHost LLAgent::getRegionHost() const
- {
- if (mRegionp)
- {
- return mRegionp->getHost();
- }
- else
- {
- return LLHost::invalid;
- }
- }
- //-----------------------------------------------------------------------------
- // inPrelude()
- //-----------------------------------------------------------------------------
- BOOL LLAgent::inPrelude()
- {
- return mRegionp && mRegionp->isPrelude();
- }
- //-----------------------------------------------------------------------------
- // canManageEstate()
- //-----------------------------------------------------------------------------
- BOOL LLAgent::canManageEstate() const
- {
- return mRegionp && mRegionp->canManageEstate();
- }
- //-----------------------------------------------------------------------------
- // sendMessage()
- //-----------------------------------------------------------------------------
- void LLAgent::sendMessage()
- {
- if (gDisconnected)
- {
- llwarns << "Trying to send message when disconnected!" << llendl;
- return;
- }
- if (!mRegionp)
- {
- llerrs << "No region for agent yet!" << llendl;
- return;
- }
- gMessageSystem->sendMessage(mRegionp->getHost());
- }
- //-----------------------------------------------------------------------------
- // sendReliableMessage()
- //-----------------------------------------------------------------------------
- void LLAgent::sendReliableMessage()
- {
- if (gDisconnected)
- {
- lldebugs << "Trying to send message when disconnected!" << llendl;
- return;
- }
- if (!mRegionp)
- {
- lldebugs << "LLAgent::sendReliableMessage No region for agent yet, not sending message!" << llendl;
- return;
- }
- gMessageSystem->sendReliable(mRegionp->getHost());
- }
- //-----------------------------------------------------------------------------
- // getVelocity()
- //-----------------------------------------------------------------------------
- LLVector3 LLAgent::getVelocity() const
- {
- if (isAgentAvatarValid())
- {
- return gAgentAvatarp->getVelocity();
- }
- else
- {
- return LLVector3::zero;
- }
- }
- //-----------------------------------------------------------------------------
- // setPositionAgent()
- //-----------------------------------------------------------------------------
- void LLAgent::setPositionAgent(const LLVector3 &pos_agent)
- {
- if (!pos_agent.isFinite())
- {
- llerrs << "setPositionAgent is not a number" << llendl;
- }
- if (isAgentAvatarValid() && gAgentAvatarp->getParent())
- {
- LLVector3 pos_agent_sitting;
- LLVector3d pos_agent_d;
- LLViewerObject *parent = (LLViewerObject*)gAgentAvatarp->getParent();
- pos_agent_sitting = gAgentAvatarp->getPosition() * parent->getRotation() + parent->getPositionAgent();
- pos_agent_d.setVec(pos_agent_sitting);
- mFrameAgent.setOrigin(pos_agent_sitting);
- mPositionGlobal = pos_agent_d + mAgentOriginGlobal;
- }
- else
- {
- mFrameAgent.setOrigin(pos_agent);
- LLVector3d pos_agent_d;
- pos_agent_d.setVec(pos_agent);
- mPositionGlobal = pos_agent_d + mAgentOriginGlobal;
- }
- }
- //-----------------------------------------------------------------------------
- // getPositionGlobal()
- //-----------------------------------------------------------------------------
- const LLVector3d &LLAgent::getPositionGlobal() const
- {
- if (isAgentAvatarValid() && !gAgentAvatarp->mDrawable.isNull())
- {
- mPositionGlobal = getPosGlobalFromAgent(gAgentAvatarp->getRenderPosition());
- }
- else
- {
- mPositionGlobal = getPosGlobalFromAgent(mFrameAgent.getOrigin());
- }
- return mPositionGlobal;
- }
- //-----------------------------------------------------------------------------
- // getPositionAgent()
- //-----------------------------------------------------------------------------
- const LLVector3 &LLAgent::getPositionAgent()
- {
- if (isAgentAvatarValid() && !gAgentAvatarp->mDrawable.isNull())
- {
- mFrameAgent.setOrigin(gAgentAvatarp->getRenderPosition());
- }
- return mFrameAgent.getOrigin();
- }
- //-----------------------------------------------------------------------------
- // getRegionsVisited()
- //-----------------------------------------------------------------------------
- S32 LLAgent::getRegionsVisited() const
- {
- return mRegionsVisited.size();
- }
- //-----------------------------------------------------------------------------
- // getDistanceTraveled()
- //-----------------------------------------------------------------------------
- F64 LLAgent::getDistanceTraveled() const
- {
- return mDistanceTraveled;
- }
- //-----------------------------------------------------------------------------
- // getPosAgentFromGlobal()
- //-----------------------------------------------------------------------------
- LLVector3 LLAgent::getPosAgentFromGlobal(const LLVector3d &pos_global) const
- {
- LLVector3 pos_agent;
- pos_agent.setVec(pos_global - mAgentOriginGlobal);
- return pos_agent;
- }
- //-----------------------------------------------------------------------------
- // getPosGlobalFromAgent()
- //-----------------------------------------------------------------------------
- LLVector3d LLAgent::getPosGlobalFromAgent(const LLVector3 &pos_agent) const
- {
- LLVector3d pos_agent_d;
- pos_agent_d.setVec(pos_agent);
- return pos_agent_d + mAgentOriginGlobal;
- }
- void LLAgent::sitDown()
- {
- setControlFlags(AGENT_CONTROL_SIT_ON_GROUND);
- }
- //-----------------------------------------------------------------------------
- // resetAxes()
- //-----------------------------------------------------------------------------
- void LLAgent::resetAxes()
- {
- mFrameAgent.resetAxes();
- }
- // Copied from LLCamera::setOriginAndLookAt
- // Look_at must be unit vector
- //-----------------------------------------------------------------------------
- // resetAxes()
- //-----------------------------------------------------------------------------
- void LLAgent::resetAxes(const LLVector3 &look_at)
- {
- LLVector3 skyward = getReferenceUpVector();
- // if look_at has zero length, fail
- // if look_at and skyward are parallel, fail
- //
- // Test both of these conditions with a cross product.
- LLVector3 cross(look_at % skyward);
- if (cross.isNull())
- {
- llinfos << "LLAgent::resetAxes cross-product is zero" << llendl;
- return;
- }
- // Make sure look_at and skyward are not parallel
- // and neither are zero length
- LLVector3 left(skyward % look_at);
- LLVector3 up(look_at % left);
- mFrameAgent.setAxes(look_at, left, up);
- }
- //-----------------------------------------------------------------------------
- // rotate()
- //-----------------------------------------------------------------------------
- void LLAgent::rotate(F32 angle, const LLVector3 &axis)
- {
- mFrameAgent.rotate(angle, axis);
- }
- //-----------------------------------------------------------------------------
- // rotate()
- //-----------------------------------------------------------------------------
- void LLAgent::rotate(F32 angle, F32 x, F32 y, F32 z)
- {
- mFrameAgent.rotate(angle, x, y, z);
- }
- //-----------------------------------------------------------------------------
- // rotate()
- //-----------------------------------------------------------------------------
- void LLAgent::rotate(const LLMatrix3 &matrix)
- {
- mFrameAgent.rotate(matrix);
- }
- //-----------------------------------------------------------------------------
- // rotate()
- //-----------------------------------------------------------------------------
- void LLAgent::rotate(const LLQuaternion &quaternion)
- {
- mFrameAgent.rotate(quaternion);
- }
- //-----------------------------------------------------------------------------
- // getReferenceUpVector()
- //-----------------------------------------------------------------------------
- LLVector3 LLAgent::getReferenceUpVector()
- {
- // this vector is in the coordinate frame of the avatar's parent object, or the world if none
- LLVector3 up_vector = LLVector3::z_axis;
- if (isAgentAvatarValid() &&
- gAgentAvatarp->getParent() &&
- gAgentAvatarp->mDrawable.notNull())
- {
- U32 camera_mode = gAgentCamera.getCameraAnimating() ? gAgentCamera.getLastCameraMode() : gAgentCamera.getCameraMode();
- // and in third person...
- if (camera_mode == CAMERA_MODE_THIRD_PERSON)
- {
- // make the up vector point to the absolute +z axis
- up_vector = up_vector * ~((LLViewerObject*)gAgentAvatarp->getParent())->getRenderRotation();
- }
- else if (camera_mode == CAMERA_MODE_MOUSELOOK)
- {
- // make the up vector point to the avatar's +z axis
- up_vector = up_vector * gAgentAvatarp->mDrawable->getRotation();
- }
- }
- return up_vector;
- }
- // Radians, positive is forward into ground
- //-----------------------------------------------------------------------------
- // pitch()
- //-----------------------------------------------------------------------------
- void LLAgent::pitch(F32 angle)
- {
- // don't let user pitch if pointed almost all the way down or up
- mFrameAgent.pitch(clampPitchToLimits(angle));
- }
- // Radians, positive is forward into ground
- //-----------------------------------------------------------------------------
- // clampPitchToLimits()
- //-----------------------------------------------------------------------------
- F32 LLAgent::clampPitchToLimits(F32 angle)
- {
- // A dot B = mag(A) * mag(B) * cos(angle between A and B)
- // so... cos(angle between A and B) = A dot B / mag(A) / mag(B)
- // = A dot B for unit vectors
- LLVector3 skyward = getReferenceUpVector();
- const F32 look_down_limit = 179.f * DEG_TO_RAD;;
- const F32 look_up_limit = 1.f * DEG_TO_RAD;
- F32 angle_from_skyward = acos( mFrameAgent.getAtAxis() * skyward );
- // clamp pitch to limits
- if ((angle >= 0.f) && (angle_from_skyward + angle > look_down_limit))
- {
- angle = look_down_limit - angle_from_skyward;
- }
- else if ((angle < 0.f) && (angle_from_skyward + angle < look_up_limit))
- {
- angle = look_up_limit - angle_from_skyward;
- }
-
- return angle;
- }
- //-----------------------------------------------------------------------------
- // roll()
- //-----------------------------------------------------------------------------
- void LLAgent::roll(F32 angle)
- {
- mFrameAgent.roll(angle);
- }
- //-----------------------------------------------------------------------------
- // yaw()
- //-----------------------------------------------------------------------------
- void LLAgent::yaw(F32 angle)
- {
- if (!rotateGrabbed())
- {
- mFrameAgent.rotate(angle, getReferenceUpVector());
- }
- }
- // Returns a quat that represents the rotation of the agent in the absolute frame
- //-----------------------------------------------------------------------------
- // getQuat()
- //-----------------------------------------------------------------------------
- LLQuaternion LLAgent::getQuat() const
- {
- return mFrameAgent.getQuaternion();
- }
- //-----------------------------------------------------------------------------
- // getControlFlags()
- //-----------------------------------------------------------------------------
- U32 LLAgent::getControlFlags()
- {
- return mControlFlags;
- }
- //-----------------------------------------------------------------------------
- // setControlFlags()
- //-----------------------------------------------------------------------------
- void LLAgent::setControlFlags(U32 mask)
- {
- mControlFlags |= mask;
- mbFlagsDirty = TRUE;
- }
- //-----------------------------------------------------------------------------
- // clearControlFlags()
- //-----------------------------------------------------------------------------
- void LLAgent::clearControlFlags(U32 mask)
- {
- U32 old_flags = mControlFlags;
- mControlFlags &= ~mask;
- if (old_flags != mControlFlags)
- {
- mbFlagsDirty = TRUE;
- }
- }
- //-----------------------------------------------------------------------------
- // controlFlagsDirty()
- //-----------------------------------------------------------------------------
- BOOL LLAgent::controlFlagsDirty() const
- {
- return mbFlagsDirty;
- }
- //-----------------------------------------------------------------------------
- // enableControlFlagReset()
- //-----------------------------------------------------------------------------
- void LLAgent::enableControlFlagReset()
- {
- mbFlagsNeedReset = TRUE;
- }
- //-----------------------------------------------------------------------------
- // resetControlFlags()
- //-----------------------------------------------------------------------------
- void LLAgent::resetControlFlags()
- {
- if (mbFlagsNeedReset)
- {
- mbFlagsNeedReset = FALSE;
- mbFlagsDirty = FALSE;
- // reset all of the ephemeral flags
- // some flags are managed elsewhere
- mControlFlags &= AGENT_CONTROL_AWAY | AGENT_CONTROL_FLY | AGENT_CONTROL_MOUSELOOK;
- }
- }
- //-----------------------------------------------------------------------------
- // setAFK()
- //-----------------------------------------------------------------------------
- void LLAgent::setAFK()
- {
- if (!gAgent.getRegion())
- {
- // Don't set AFK if we're not talking to a region yet.
- return;
- }
- if (!(mControlFlags & AGENT_CONTROL_AWAY))
- {
- sendAnimationRequest(ANIM_AGENT_AWAY, ANIM_REQUEST_START);
- setControlFlags(AGENT_CONTROL_AWAY | AGENT_CONTROL_STOP);
- LL_INFOS("AFK") << "Setting Away" << LL_ENDL;
- gAwayTimer.start();
- if (gAFKMenu)
- {
- gAFKMenu->setLabel(LLTrans::getString("AvatarSetNotAway"));
- }
- }
- }
- //-----------------------------------------------------------------------------
- // clearAFK()
- //-----------------------------------------------------------------------------
- void LLAgent::clearAFK()
- {
- gAwayTriggerTimer.reset();
- // Gods can sometimes get into away state (via gestures)
- // without setting the appropriate control flag. JC
- if (mControlFlags & AGENT_CONTROL_AWAY
- || (isAgentAvatarValid()
- && (gAgentAvatarp->mSignaledAnimations.find(ANIM_AGENT_AWAY) != gAgentAvatarp->mSignaledAnimations.end())))
- {
- sendAnimationRequest(ANIM_AGENT_AWAY, ANIM_REQUEST_STOP);
- clearControlFlags(AGENT_CONTROL_AWAY);
- LL_INFOS("AFK") << "Clearing Away" << LL_ENDL;
- if (gAFKMenu)
- {
- gAFKMenu->setLabel(LLTrans::getString("AvatarSetAway"));
- }
- }
- }
- //-----------------------------------------------------------------------------
- // getAFK()
- //-----------------------------------------------------------------------------
- BOOL LLAgent::getAFK() const
- {
- return (mControlFlags & AGENT_CONTROL_AWAY) != 0;
- }
- //-----------------------------------------------------------------------------
- // setBusy()
- //-----------------------------------------------------------------------------
- void LLAgent::setBusy()
- {
- sendAnimationRequest(ANIM_AGENT_BUSY, ANIM_REQUEST_START);
- mIsBusy = TRUE;
- if (gBusyMenu)
- {
- gBusyMenu->setLabel(LLTrans::getString("AvatarSetNotBusy"));
- }
- LLNotificationsUI::LLChannelManager::getInstance()->muteAllChannels(true);
- }
- //-----------------------------------------------------------------------------
- // clearBusy()
- //-----------------------------------------------------------------------------
- void LLAgent::clearBusy()
- {
- mIsBusy = FALSE;
- sendAnimationRequest(ANIM_AGENT_BUSY, ANIM_REQUEST_STOP);
- if (gBusyMenu)
- {
- gBusyMenu->setLabel(LLTrans::getString("AvatarSetBusy"));
- }
- LLNotificationsUI::LLChannelManager::getInstance()->muteAllChannels(false);
- }
- //-----------------------------------------------------------------------------
- // getBusy()
- //-----------------------------------------------------------------------------
- BOOL LLAgent::getBusy() const
- {
- return mIsBusy;
- }
- //-----------------------------------------------------------------------------
- // startAutoPilotGlobal()
- //-----------------------------------------------------------------------------
- void LLAgent::startAutoPilotGlobal(
- const LLVector3d &target_global,
- const std::string& behavior_name,
- const LLQuaternion *target_rotation,
- void (*finish_callback)(BOOL, void *),
- void *callback_data,
- F32 stop_distance,
- F32 rot_threshold,
- BOOL allow_flying)
- {
- if (!isAgentAvatarValid())
- {
- return;
- }
-
- // Are there any pending callbacks from previous auto pilot requests?
- if (mAutoPilotFinishedCallback)
- {
- mAutoPilotFinishedCallback(dist_vec(gAgent.getPositionGlobal(), mAutoPilotTargetGlobal) < mAutoPilotStopDistance, mAutoPilotCallbackData);
- }
- mAutoPilotFinishedCallback = finish_callback;
- mAutoPilotCallbackData = callback_data;
- mAutoPilotRotationThreshold = rot_threshold;
- mAutoPilotBehaviorName = behavior_name;
- mAutoPilotAllowFlying = allow_flying;
- LLVector3d delta_pos( target_global );
- delta_pos -= getPositionGlobal();
- F64 distance = delta_pos.magVec();
- LLVector3d trace_target = target_global;
- trace_target.mdV[VZ] -= 10.f;
- LLVector3d intersection;
- LLVector3 normal;
- LLViewerObject *hit_obj;
- F32 heightDelta = LLWorld::getInstance()->resolveStepHeightGlobal(NULL, target_global, trace_target, intersection, normal, &hit_obj);
- if (stop_distance > 0.f)
- {
- mAutoPilotStopDistance = stop_distance;
- }
- else
- {
- // Guess at a reasonable stop distance.
- mAutoPilotStopDistance = (F32) sqrt( distance );
- if (mAutoPilotStopDistance < 0.5f)
- {
- mAutoPilotStopDistance = 0.5f;
- }
- }
- if (mAutoPilotAllowFlying)
- {
- mAutoPilotFlyOnStop = getFlying();
- }
- else
- {
- mAutoPilotFlyOnStop = FALSE;
- }
- if (distance > 30.0 && mAutoPilotAllowFlying)
- {
- setFlying(TRUE);
- }
- if ( distance > 1.f &&
- mAutoPilotAllowFlying &&
- heightDelta > (sqrtf(mAutoPilotStopDistance) + 1.f))
- {
- setFlying(TRUE);
- // Do not force flying for "Sit" behavior to prevent flying after pressing "Stand"
- // from an object. See EXT-1655.
- if ("Sit" != mAutoPilotBehaviorName)
- mAutoPilotFlyOnStop = TRUE;
- }
- mAutoPilot = TRUE;
- setAutoPilotTargetGlobal(target_global);
- if (target_rotation)
- {
- mAutoPilotUseRotation = TRUE;
- mAutoPilotTargetFacing = LLVector3::x_axis * *target_rotation;
- mAutoPilotTargetFacing.mV[VZ] = 0.f;
- mAutoPilotTargetFacing.normalize();
- }
- else
- {
- mAutoPilotUseRotation = FALSE;
- }
- mAutoPilotNoProgressFrameCount = 0;
- }
- //-----------------------------------------------------------------------------
- // setAutoPilotTargetGlobal
- //-----------------------------------------------------------------------------
- void LLAgent::setAutoPilotTargetGlobal(const LLVector3d &target_global)
- {
- if (mAutoPilot)
- {
- mAutoPilotTargetGlobal = target_global;
- // trace ray down to find height of destination from ground
- LLVector3d traceEndPt = target_global;
- traceEndPt.mdV[VZ] -= 20.f;
- LLVector3d targetOnGround;
- LLVector3 groundNorm;
- LLViewerObject *obj;
- LLWorld::getInstance()->resolveStepHeightGlobal(NULL, target_global, traceEndPt, targetOnGround, groundNorm, &obj);
- F64 target_height = llmax((F64)gAgentAvatarp->getPelvisToFoot(), target_global.mdV[VZ] - targetOnGround.mdV[VZ]);
- // clamp z value of target to minimum height above ground
- mAutoPilotTargetGlobal.mdV[VZ] = targetOnGround.mdV[VZ] + target_height;
- mAutoPilotTargetDist = (F32)dist_vec(gAgent.getPositionGlobal(), mAutoPilotTargetGlobal);
- }
- }
- //-----------------------------------------------------------------------------
- // startFollowPilot()
- //-----------------------------------------------------------------------------
- void LLAgent::startFollowPilot(const LLUUID &leader_id, BOOL allow_flying, F32 stop_distance)
- {
- mLeaderID = leader_id;
- if ( mLeaderID.isNull() ) return;
- LLViewerObject* object = gObjectList.findObject(mLeaderID);
- if (!object)
- {
- mLeaderID = LLUUID::null;
- return;
- }
- startAutoPilotGlobal(object->getPositionGlobal(),
- std::string(), // behavior_name
- NULL, // target_rotation
- NULL, // finish_callback
- NULL, // callback_data
- stop_distance,
- 0.03f, // rotation_threshold
- allow_flying);
- }
- //-----------------------------------------------------------------------------
- // stopAutoPilot()
- //-----------------------------------------------------------------------------
- void LLAgent::stopAutoPilot(BOOL user_cancel)
- {
- if (mAutoPilot)
- {
- mAutoPilot = FALSE;
- if (mAutoPilotUseRotation && !user_cancel)
- {
- resetAxes(mAutoPilotTargetFacing);
- }
- // Restore previous flying state before invoking mAutoPilotFinishedCallback to allow
- // callback function to change the flying state (like in near_sit_down_point()).
- // If the user cancelled, don't change the fly state
- if (!user_cancel)
- {
- setFlying(mAutoPilotFlyOnStop);
- }
- //NB: auto pilot can terminate for a reason other than reaching the destination
- if (mAutoPilotFinishedCallback)
- {
- mAutoPilotFinishedCallback(!user_cancel && dist_vec(gAgent.getPositionGlobal(), mAutoPilotTargetGlobal) < mAutoPilotStopDistance, mAutoPilotCallbackData);
- mAutoPilotFinishedCallback = NULL;
- }
- mLeaderID = LLUUID::null;
- setControlFlags(AGENT_CONTROL_STOP);
- if (user_cancel && !mAutoPilotBehaviorName.empty())
- {
- if (mAutoPilotBehaviorName == "Sit")
- LLNotificationsUtil::add("CancelledSit");
- else if (mAutoPilotBehaviorName == "Attach")
- LLNotificationsUtil::add("CancelledAttach");
- else
- LLNotificationsUtil::add("Cancelled");
- }
- }
- }
- // Returns necessary agent pitch and yaw changes, radians.
- //-----------------------------------------------------------------------------
- // autoPilot()
- //-----------------------------------------------------------------------------
- void LLAgent::autoPilot(F32 *delta_yaw)
- {
- if (mAutoPilot)
- {
- if (!mLeaderID.isNull())
- {
- LLViewerObject* object = gObjectList.findObject(mLeaderID);
- if (!object)
- {
- stopAutoPilot();
- return;
- }
- mAutoPilotTargetGlobal = object->getPositionGlobal();
- }
-
- if (!isAgentAvatarValid()) return;
- if (gAgentAvatarp->mInAir && mAutoPilotAllowFlying)
- {
- setFlying(TRUE);
- }
-
- LLVector3 at;
- at.setVec(mFrameAgent.getAtAxis());
- LLVector3 target_agent = getPosAgentFromGlobal(mAutoPilotTargetGlobal);
- LLVector3 direction = target_agent - getPositionAgent();
- F32 target_dist = direction.magVec();
- if (target_dist >= mAutoPilotTargetDist)
- {
- mAutoPilotNoProgressFrameCount++;
- if (mAutoPilotNoProgressFrameCount > AUTOPILOT_MAX_TIME_NO_PROGRESS * gFPSClamped)
- {
- stopAutoPilot();
- return;
- }
- }
- mAutoPilotTargetDist = target_dist;
- // Make this a two-dimensional solution
- at.mV[VZ] = 0.f;
- direction.mV[VZ] = 0.f;
- at.normalize();
- F32 xy_distance = direction.normalize();
- F32 yaw = 0.f;
- if (mAutoPilotTargetDist > mAutoPilotStopDistance)
- {
- yaw = angle_between(mFrameAgent.getAtAxis(), direction);
- }
- else if (mAutoPilotUseRotation)
- {
- // we're close now just aim at target facing
- yaw = angle_between(at, mAutoPilotTargetFacing);
- direction = mAutoPilotTargetFacing;
- }
- yaw = 4.f * yaw / gFPSClamped;
- // figure out which direction to turn
- LLVector3 scratch(at % direction);
- if (scratch.mV[VZ] > 0.f)
- {
- setControlFlags(AGENT_CONTROL_YAW_POS);
- }
- else
- {
- yaw = -yaw;
- setControlFlags(AGENT_CONTROL_YAW_NEG);
- }
- *delta_yaw = yaw;
- // Compute when to start slowing down and when to stop
- F32 stop_distance = mAutoPilotStopDistance;
- F32 slow_distance;
- if (getFlying())
- {
- slow_distance = llmax(6.f, mAutoPilotStopDistance + 5.f);
- stop_distance = llmax(2.f, mAutoPilotStopDistance);
- }
- else
- {
- slow_distance = llmax(3.f, mAutoPilotStopDistance + 2.f);
- }
- // If we're flying, handle autopilot points above or below you.
- if (getFlying() && xy_distance < AUTOPILOT_HEIGHT_ADJUST_DISTANCE)
- {
- if (isAgentAvatarValid())
- {
- F64 current_height = gAgentAvatarp->getPositionGlobal().mdV[VZ];
- F32 delta_z = (F32)(mAutoPilotTargetGlobal.mdV[VZ] - current_height);
- F32 slope = delta_z / xy_distance;
- if (slope > 0.45f && delta_z > 6.f)
- {
- setControlFlags(AGENT_CONTROL_FAST_UP | AGENT_CONTROL_UP_POS);
- }
- else if (slope > 0.002f && delta_z > 0.5f)
- {
- setControlFlags(AGENT_CONTROL_UP_POS);
- }
- else if (slope < -0.45f && delta_z < -6.f && current_height > AUTOPILOT_MIN_TARGET_HEIGHT_OFF_GROUND)
- {
- setControlFlags(AGENT_CONTROL_FAST_UP | AGENT_CONTROL_UP_NEG);
- }
- else if (slope < -0.002f && delta_z < -0.5f && current_height > AUTOPILOT_MIN_TARGET_HEIGHT_OFF_GROUND)
- {
- setControlFlags(AGENT_CONTROL_UP_NEG);
- }
- }
- }
- // calculate delta rotation to target heading
- F32 delta_target_heading = angle_between(mFrameAgent.getAtAxis(), mAutoPilotTargetFacing);
- if (xy_distance > slow_distance && yaw < (F_PI / 10.f))
- {
- // walking/flying fast
- setControlFlags(AGENT_CONTROL_FAST_AT | AGENT_CONTROL_AT_POS);
- }
- else if (mAutoPilotTargetDist > mAutoPilotStopDistance)
- {
- // walking/flying slow
- if (at * direction > 0.9f)
- {
- setControlFlags(AGENT_CONTROL_AT_POS);
- }
- else if (at * direction < -0.9f)
- {
- setControlFlags(AGENT_CONTROL_AT_NEG);
- }
- }
- // check to see if we need to keep rotating to target orientation
- if (mAutoPilotTargetDist < mAutoPilotStopDistance)
- {
- setControlFlags(AGENT_CONTROL_STOP);
- if(!mAutoPilotUseRotation || (delta_target_heading < mAutoPilotRotationThreshold))
- {
- stopAutoPilot();
- }
- }
- }
- }
- //-----------------------------------------------------------------------------
- // propagate()
- //-----------------------------------------------------------------------------
- void LLAgent::propagate(const F32 dt)
- {
- // Update UI based on agent motion
- LLFloaterMove *floater_move = LLFloaterReg::findTypedInstance<LLFloaterMove>("moveview");
- if (floater_move)
- {
- floater_move->mForwardButton ->setToggleState( gAgentCamera.getAtKey() > 0 || gAgentCamera.getWalkKey() > 0 );
- floater_move->mBackwardButton ->setToggleState( gAgentCamera.getAtKey() < 0 || gAgentCamera.getWalkKey() < 0 );
- floater_move->mTurnLeftButton ->setToggleState( gAgentCamera.getYawKey() > 0.f );
- floater_move->mTurnRightButton ->setToggleState( gAgentCamera.getYawKey() < 0.f );
- floater_move->mSlideLeftButton ->setToggleState( gAgentCamera.getLeftKey() > 0.f );
- floater_move->mSlideRightButton ->setToggleState( gAgentCamera.getLeftKey() < 0.f );
- floater_move->mMoveUpButton ->setToggleState( gAgentCamera.getUpKey() > 0 );
- floater_move->mMoveDownButton ->setToggleState( gAgentCamera.getUpKey() < 0 );
- }
- // handle rotation based on keyboard levels
- const F32 YAW_RATE = 90.f * DEG_TO_RAD; // radians per second
- yaw(YAW_RATE * gAgentCamera.getYawKey() * dt);
- const F32 PITCH_RATE = 90.f * DEG_TO_RAD; // radians per second
- pitch(PITCH_RATE * gAgentCamera.getPitchKey() * dt);
-
- // handle auto-land behavior
- if (isAgentAvatarValid())
- {
- BOOL in_air = gAgentAvatarp->mInAir;
- LLVector3 land_vel = getVelocity();
- land_vel.mV[VZ] = 0.f;
- if (!in_air
- && gAgentCamera.getUpKey() < 0
- && land_vel.magVecSquared() < MAX_VELOCITY_AUTO_LAND_SQUARED
- && gSavedSettings.getBOOL("AutomaticFly"))
- {
- // land automatically
- setFlying(FALSE);
- }
- }
- gAgentCamera.clearGeneralKeys();
- }
- //-----------------------------------------------------------------------------
- // updateAgentPosition()
- //-----------------------------------------------------------------------------
- void LLAgent::updateAgentPosition(const F32 dt, const F32 yaw_radians, const S32 mouse_x, const S32 mouse_y)
- {
- if (mMoveTimer.getStarted() && mMoveTimer.getElapsedTimeF32() > gSavedSettings.getF32("NotMovingHintTimeout"))
- {
- LLFirstUse::notMoving();
- }
- propagate(dt);
- // static S32 cameraUpdateCount = 0;
- rotate(yaw_radians, 0, 0, 1);
-
- //
- // Check for water and land collision, set underwater flag
- //
- gAgentCamera.updateLookAt(mouse_x, mouse_y);
- }
- // friends and operators
- std::ostream& operator<<(std::ostream &s, const LLAgent &agent)
- {
- // This is unfinished, but might never be used.
- // We'll just leave it for now; we can always delete it.
- s << " { "
- << " Frame = " << agent.mFrameAgent << "\n"
- << " }";
- return s;
- }
- // TRUE if your own avatar needs to be rendered. Usually only
- // in third person and build.
- //-----------------------------------------------------------------------------
- // needsRenderAvatar()
- //-----------------------------------------------------------------------------
- BOOL LLAgent::needsRenderAvatar()
- {
- if (gAgentCamera.cameraMouselook() && !LLVOAvatar::sVisibleInFirstPerson)
- {
- return FALSE;
- }
- return mShowAvatar && mGenderChosen;
- }
- // TRUE if we need to render your own avatar's head.
- BOOL LLAgent::needsRenderHead()
- {
- return (LLVOAvatar::sVisibleInFirstPerson && LLPipeline::sReflectionRender) || (mShowAvatar && !gAgentCamera.cameraMouselook());
- }
- //-----------------------------------------------------------------------------
- // startTyping()
- //-----------------------------------------------------------------------------
- void LLAgent::startTyping()
- {
- mTypingTimer.reset();
- if (getRenderState() & AGENT_STATE_TYPING)
- {
- // already typing, don't trigger a different animation
- return;
- }
- setRenderState(AGENT_STATE_TYPING);
- if (mChatTimer.getElapsedTimeF32() < 2.f)
- {
- LLViewerObject* chatter = gObjectList.findObject(mLastChatterID);
- if (chatter && chatter->isAvatar())
- {
- gAgentCamera.setLookAt(LOOKAT_TARGET_RESPOND, chatter, LLVector3::zero);
- }
- }
- if (gSavedSettings.getBOOL("PlayTypingAnim"))
- {
- sendAnimationRequest(ANIM_AGENT_TYPE, ANIM_REQUEST_START);
- }
- LLNearbyChatBar::getInstance()->sendChatFromViewer("", CHAT_TYPE_START, FALSE);
- }
- //-----------------------------------------------------------------------------
- // stopTyping()
- //-----------------------------------------------------------------------------
- void LLAgent::stopTyping()
- {
- if (mRenderState & AGENT_STATE_TYPING)
- {
- clearRenderState(AGENT_STATE_TYPING);
- sendAnimationRequest(ANIM_AGENT_TYPE, ANIM_REQUEST_STOP);
- LLNearbyChatBar::getInstance()->sendChatFromViewer("", CHAT_TYPE_STOP, FALSE);
- }
- }
- //-----------------------------------------------------------------------------
- // setRenderState()
- //-----------------------------------------------------------------------------
- void LLAgent::setRenderState(U8 newstate)
- {
- mRenderState |= newstate;
- }
- //-----------------------------------------------------------------------------
- // clearRenderState()
- //-----------------------------------------------------------------------------
- void LLAgent::clearRenderState(U8 clearstate)
- {
- mRenderState &= ~clearstate;
- }
- //-----------------------------------------------------------------------------
- // getRenderState()
- //-----------------------------------------------------------------------------
- U8 LLAgent::getRenderState()
- {
- // *FIX: don't do stuff in a getter! This is infinite loop city!
- if ((mTypingTimer.getElapsedTimeF32() > TYPING_TIMEOUT_SECS)
- && (mRenderState & AGENT_STATE_TYPING))
- {
- stopTyping();
- }
-
- if ((!LLSelectMgr::getInstance()->getSelection()->isEmpty() && LLSelectMgr::getInstance()->shouldShowSelection())
- || LLToolMgr::getInstance()->getCurrentTool()->isEditing() )
- {
- setRenderState(AGENT_STATE_EDITING);
- }
- else
- {
- clearRenderState(AGENT_STATE_EDITING);
- }
- return mRenderState;
- }
- //-----------------------------------------------------------------------------
- //-----------------------------------------------------------------------------
- //-----------------------------------------------------------------------------
- // endAnimationUpdateUI()
- //-----------------------------------------------------------------------------
- void LLAgent::endAnimationUpdateUI()
- {
- if (gAgentCamera.getCameraMode() == gAgentCamera.getLastCameraMode())
- {
- // We're already done endAnimationUpdateUI for this transition.
- return;
- }
- // clean up UI from mode we're leaving
- if (gAgentCamera.getLastCameraMode() == CAMERA_MODE_MOUSELOOK )
- {
- gToolBarView->setToolBarsVisible(true);
- // show mouse cursor
- gViewerWindow->showCursor();
- // show menus
- gMenuBarView->setVisible(TRUE);
- LLNavigationBar::getInstance()->setVisible(TRUE && gSavedSettings.getBOOL("ShowNavbarNavigationPanel"));
- gStatusBar->setVisibleForMouselook(true);
- if (gSavedSettings.getBOOL("ShowMiniLocationPanel"))
- {
- LLPanelTopInfoBar::getInstance()->setVisible(TRUE);
- }
- LLChicletBar::getInstance()->setVisible(TRUE);
- LLPanelStandStopFlying::getInstance()->setVisible(TRUE);
- LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset);
- LLFloaterCamera::onLeavingMouseLook();
- if (mMouselookModeOutSignal)
- {
- (*mMouselookModeOutSignal)();
- }
- // Only pop if we have pushed...
- if (TRUE == mViewsPushed)
- {
- #if 0 // Use this once all floaters are registered
- LLFloaterReg::restoreVisibleInstances();
- #else // Use this for now
- LLFloaterView::skip_list_t skip_list;
- if (LLFloaterReg::findInstance("mini_map"))
- {
- skip_list.insert(LLFloaterReg::findInstance("mini_map"));
- }
-
- gFloaterView->popVisibleAll(skip_list);
- #endif
- mViewsPushed = FALSE;
- }
-
- gAgentCamera.setLookAt(LOOKAT_TARGET_CLEAR);
- if( gMorphView )
- {
- gMorphView->setVisible( FALSE );
- }
- // Disable mouselook-specific animations
- if (isAgentAvatarValid())
- {
- if( gAgentAvatarp->isAnyAnimationSignaled(AGENT_GUN_AIM_ANIMS, NUM_AGENT_GUN_AIM_ANIMS) )
- {
- if (gAgentAvatarp->mSignaledAnimations.find(ANIM_AGENT_AIM_RIFLE_R) != gAgentAvatarp->mSignaledAnimations.end())
- {
- sendAnimationRequest(ANIM_AGENT_AIM_RIFLE_R, ANIM_REQUEST_STOP);
- sendAnimationRequest(ANIM_AGENT_HOLD_RIFLE_R, ANIM_REQUEST_START);
- }
- if (gAgentAvatarp->mSignaledAnimations.find(ANIM_AGENT_AIM_HANDGUN_R) != gAgentAvatarp->mSignaledAnimations.end())
- {
- sendAnimationRequest(ANIM_AGENT_AIM_HANDGUN_R, ANIM_REQUEST_STOP);
- sendAnimationRequest(ANIM_AGENT_HOLD_HANDGUN_R, ANIM_REQUEST_START);
- }
- if (gAgentAvatarp->mSignaledAnimations.find(ANIM_AGENT_AIM_BAZOOKA_R) != gAgentAvatarp->mSignaledAnimations.end())
- {
- sendAnimationRequest(ANIM_AGENT_AIM_BAZOOKA_R, ANIM_REQUEST_STOP);
- sendAnimationRequest(ANIM_AGENT_HOLD_BAZOOKA_R, ANIM_REQUEST_START);
- }
- if (gAgentAvatarp->mSignaledAnimations.find(ANIM_AGENT_AIM_BOW_L) != gAgentAvatarp->mSignaledAnimations.end())
- {
- sendAnimationRequest(ANIM_AGENT_AIM_BOW_L, ANIM_REQUEST_STOP);
- sendAnimationRequest(ANIM_AGENT_HOLD_BOW_L, ANIM_REQUEST_START);
- }
- }
- }
- }
- else if (gAgentCamera.getLastCameraMode() == CAMERA_MODE_CUSTOMIZE_AVATAR)
- {
- // make sure we ask to save changes
- LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset);
- if( gMorphView )
- {
- gMorphView->setVisible( FALSE );
- }
- if (isAgentAvatarValid())
- {
- if(mCustomAnim)
- {
- sendAnimationRequest(ANIM_AGENT_CUSTOMIZE, ANIM_REQUEST_STOP);
- sendAnimationRequest(ANIM_AGENT_CUSTOMIZE_DONE, ANIM_REQUEST_START);
- mCustomAnim = FALSE ;
- }
-
- }
- gAgentCamera.setLookAt(LOOKAT_TARGET_CLEAR);
- LLFloaterCamera::onAvatarEditingAppearance(false);
- }
- //---------------------------------------------------------------------
- // Set up UI for mode we're entering
- //---------------------------------------------------------------------
- if (gAgentCamera.getCameraMode() == CAMERA_MODE_MOUSELOOK)
- {
- // clean up UI
- // first show anything hidden by UI toggle
- gViewerWindow->setUIVisibility(TRUE);
- // then hide stuff we want hidden for mouselook
- gToolBarView->setToolBarsVisible(false);
- gMenuBarView->setVisible(FALSE);
- LLNavigationBar::getInstance()->setVisible(FALSE);
- gStatusBar->setVisibleForMouselook(false);
- LLPanelTopInfoBar::getInstance()->setVisible(FALSE);
- LLChicletBar::getInstance()->setVisible(FALSE);
- LLPanelStandStopFlying::getInstance()->setVisible(FALSE);
- // clear out camera lag effect
- gAgentCamera.clearCameraLag();
- // JC - Added for always chat in third person option
- gFocusMgr.setKeyboardFocus(NULL);
- LLToolMgr::getInstance()->setCurrentToolset(gMouselookToolset);
- mViewsPushed = TRUE;
- if (mMouselookModeInSignal)
- {
- (*mMouselookModeInSignal)();
- }
- // hide all floaters except the mini map
- #if 0 // Use this once all floaters are registered
- std::set<std::string> exceptions;
- exceptions.insert("mini_map");
- LLFloaterReg::hideVisibleInstances(exceptions);
- #else // Use this for now
- LLFloaterView::skip_list_t skip_list;
- skip_list.insert(LLFloaterReg::findInstance("mini_map"));
- gFloaterView->pushVisibleAll(FALSE, skip_list);
- #endif
- if( gMorphView )
- {
- gMorphView->setVisible(FALSE);
- }
- gConsole->setVisible( TRUE );
- if (isAgentAvatarValid())
- {
- // Trigger mouselook-specific animations
- if( gAgentAvatarp->isAnyAnimationSignaled(AGENT_GUN_HOLD_ANIMS, NUM_AGENT_GUN_HOLD_ANIMS) )
- {
- if (gAgentAvatarp->mSignaledAnimations.find(ANIM_AGENT_HOLD_RIFLE_R) != gAgentAvatarp->mSignaledAnimations.end())
- {
- sendAnimationRequest(ANIM_AGENT_HOLD_RIFLE_R, ANIM_REQUEST_STOP);
- sendAnimationRequest(ANIM_AGENT_AIM_RIFLE_R, ANIM_REQUEST_START);
- }
- if (gAgentAvatarp->mSignaledAnimations.find(ANIM_AGENT_HOLD_HANDGUN_R) != gAgentAvatarp->mSignaledAnimations.end())
- {
- sendAnimationRequest(ANIM_AGENT_HOLD_HANDGUN_R, ANIM_REQUEST_STOP);
- sendAnimationRequest(ANIM_AGENT_AIM_HANDGUN_R, ANIM_REQUEST_START);
- }
- if (gAgentAvatarp->mSignaledAnimations.find(ANIM_AGENT_HOLD_BAZOOKA_R) != gAgentAvatarp->mSignaledAnimations.end())
- {
- sendAnimationRequest(ANIM_AGENT_HOLD_BAZOOKA_R, ANIM_REQUEST_STOP);
- sendAnimationRequest(ANIM_AGENT_AIM_BAZOOKA_R, ANIM_REQUEST_START);
- }
- if (gAgentAvatarp->mSignaledAnimations.find(ANIM_AGENT_HOLD_BOW_L) != gAgentAvatarp->mSignaledAnimations.end())
- {
- sendAnimationRequest(ANIM_AGENT_HOLD_BOW_L, ANIM_REQUEST_STOP);
- sendAnimationRequest(ANIM_AGENT_AIM_BOW_L, ANIM_REQUEST_START);
- }
- }
- if (gAgentAvatarp->getParent())
- {
- LLVector3 at_axis = LLViewerCamera::getInstance()->getAtAxis();
- LLViewerObject* root_object = (LLViewerObject*)gAgentAvatarp->getRoot();
- if (root_object->flagCameraDecoupled())
- {
- resetAxes(at_axis);
- }
- else
- {
- resetAxes(at_axis * ~((LLViewerObject*)gAgentAvatarp->getParent())->getRenderRotation());
- }
- }
- }
- }
- else if (gAgentCamera.getCameraMode() == CAMERA_MODE_CUSTOMIZE_AVATAR)
- {
- LLToolMgr::getInstance()->setCurrentToolset(gFaceEditToolset);
- if( gMorphView )
- {
- gMorphView->setVisible( TRUE );
- }
- // freeze avatar
- if (isAgentAvatarValid())
- {
- mPauseRequest = gAgentAvatarp->requestPause();
- }
- LLFloaterCamera::onAvatarEditingAppearance(true);
- }
- if (isAgentAvatarValid())
- {
- gAgentAvatarp->updateAttachmentVisibility(gAgentCamera.getCameraMode());
- }
- gFloaterTools->dirty();
- // Don't let this be called more than once if the camera
- // mode hasn't changed. --JC
- gAgentCamera.updateLastCamera();
- }
- boost::signals2::connection LLAgent::setMouselookModeInCallback( const camera_signal_t::slot_type& cb )
- {
- if (!mMouselookModeInSignal) mMouselookModeInSignal = new camera_signal_t();
- return mMouselookModeInSignal->connect(cb);
- }
- boost::signals2::connection LLAgent::setMouselookModeOutCallback( const camera_signal_t::slot_type& cb )
- {
- if (!mMouselookModeOutSignal) mMouselookModeOutSignal = new camera_signal_t();
- return mMouselookModeOutSignal->connect(cb);
- }
- //-----------------------------------------------------------------------------
- // heardChat()
- //-----------------------------------------------------------------------------
- void LLAgent::heardChat(const LLUUID& id)
- {
- // log text and voice chat to speaker mgr
- // for keeping track of active speakers, etc.
- LLLocalSpeakerMgr::getInstance()->speakerChatted(id);
- // don't respond to your own voice
- if (id == getID()) return;
-
- if (ll_rand(2) == 0)
- {
- LLViewerObject *chatter = gObjectList.findObject(mLastChatterID);
- gAgentCamera.setLookAt(LOOKAT_TARGET_AUTO_LISTEN, chatter, LLVector3::zero);
- }
- mLastChatterID = id;
- mChatTimer.reset();
- }
- const F32 SIT_POINT_EXTENTS = 0.2f;
- LLSD ll_sdmap_from_vector3(const LLVector3& vec)
- {
- LLSD ret;
- ret["X"] = vec.mV[VX];
- ret["Y"] = vec.mV[VY];
- ret["Z"] = vec.mV[VZ];
- return ret;
- }
- LLVector3 ll_vector3_from_sdmap(const LLSD& sd)
- {
- LLVector3 ret;
- ret.mV[VX] = F32(sd["X"].asReal());
- ret.mV[VY] = F32(sd["Y"].asReal());
- ret.mV[VZ] = F32(sd["Z"].asReal());
- return ret;
- }
- void LLAgent::setStartPosition( U32 location_id )
- {
- LLViewerObject *object;
- if (gAgentID == LLUUID::null)
- {
- return;
- }
- // we've got an ID for an agent viewerobject
- object = gObjectList.findObject(gAgentID);
- if (! object)
- {
- llinfos << "setStartPosition - Can't find agent viewerobject id " << gAgentID << llendl;
- return;
- }
- // we've got the viewer object
- // Sometimes the agent can be velocity interpolated off of
- // this simulator. Clamp it to the region the agent is
- // in, a little bit in on each side.
- const F32 INSET = 0.5f; //meters
- const F32 REGION_WIDTH = LLWorld::getInstance()->getRegionWidthInMeters();
- LLVector3 agent_pos = getPositionAgent();
- if (isAgentAvatarValid())
- {
- // the z height is at the agent's feet
- agent_pos.mV[VZ] -= 0.5f * gAgentAvatarp->mBodySize.mV[VZ];
- }
- agent_pos.mV[VX] = llclamp( agent_pos.mV[VX], INSET, REGION_WIDTH - INSET );
- agent_pos.mV[VY] = llclamp( agent_pos.mV[VY], INSET, REGION_WIDTH - INSET );
- // Don't let them go below ground, or too high.
- agent_pos.mV[VZ] = llclamp( agent_pos.mV[VZ],
- mRegionp->getLandHeightRegion( agent_pos ),
- LLWorld::getInstance()->getRegionMaxHeight() );
- // Send the CapReq
- LLSD request;
- LLSD body;
- LLSD homeLocation;
- homeLocation["LocationId"] = LLSD::Integer(location_id);
- homeLocation["LocationPos"] = ll_sdmap_from_vector3(agent_pos);
- homeLocation["LocationLookAt"] = ll_sdmap_from_vector3(mFrameAgent.getAtAxis());
- body["HomeLocation"] = homeLocation;
- // This awkward idiom warrants explanation.
- // For starters, LLSDMessage::ResponderAdapter is ONLY for testing the new
- // LLSDMessage functionality with a pre-existing LLHTTPClient::Responder.
- // In new code, define your reply/error methods on the same class as the
- // sending method, bind them to local LLEventPump objects and pass those
- // LLEventPump names in the request LLSD object.
- // When testing old code, the new LLHomeLocationResponder object
- // is referenced by an LLHTTPClient::ResponderPtr, so when the
- // ResponderAdapter is deleted, the LLHomeLocationResponder will be too.
- // We must trust that the underlying LLHTTPClient code will eventually
- // fire either the reply callback or the error callback; either will cause
- // the ResponderAdapter to delete itself.
- LLSDMessage::ResponderAdapter*
- adapter(new LLSDMessage::ResponderAdapter(new LLHomeLocationResponder()));
- request["message"] = "HomeLocation";
- request["payload"] = body;
- request["reply"] = adapter->getReplyName();
- request["error"] = adapter->getErrorName();
- gAgent.getRegion()->getCapAPI().post(request);
- const U32 HOME_INDEX = 1;
- if( HOME_INDEX == location_id )
- {
- setHomePosRegion( mRegionp->getHandle(), getPositionAgent() );
- }
- }
- struct HomeLocationMapper: public LLCapabilityListener::CapabilityMapper
- {
- // No reply message expected
- HomeLocationMapper(): LLCapabilityListener::CapabilityMapper("HomeLocation") {}
- virtual void buildMessage(LLMessageSystem* msg,
- const LLUUID& agentID,
- const LLUUID& sessionID,
- const std::string& capabilityName,
- const LLSD& payload) const
- {
- msg->newMessageFast(_PREHASH_SetStartLocationRequest);
- msg->nextBlockFast( _PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, agentID);
- msg->addUUIDFast(_PREHASH_SessionID, sessionID);
- msg->nextBlockFast( _PREHASH_StartLocationData);
- // corrected by sim
- msg->addStringFast(_PREHASH_SimName, "");
- msg->addU32Fast(_PREHASH_LocationID, payload["HomeLocation"]["LocationId"].asInteger());
- msg->addVector3Fast(_PREHASH_LocationPos,
- ll_vector3_from_sdmap(payload["HomeLocation"]["LocationPos"]));
- msg->addVector3Fast(_PREHASH_LocationLookAt,
- ll_vector3_from_sdmap(payload["HomeLocation"]["LocationLookAt"]));
- }
- };
- // Need an instance of this class so it will self-register
- static HomeLocationMapper homeLocationMapper;
- void LLAgent::requestStopMotion( LLMotion* motion )
- {
- // Notify all avatars that a motion has stopped.
- // This is needed to clear the animation state bits
- LLUUID anim_state = motion->getID();
- onAnimStop(motion->getID());
- // if motion is not looping, it could have stopped by running out of time
- // so we need to tell the server this
- // llinfos << "Sending stop for motion " << motion->getName() << llendl;
- sendAnimationRequest( anim_state, ANIM_REQUEST_STOP );
- }
- void LLAgent::onAnimStop(const LLUUID& id)
- {
- // handle automatic state transitions (based on completion of animation playback)
- if (id == ANIM_AGENT_STAND)
- {
- stopFidget();
- }
- else if (id == ANIM_AGENT_AWAY)
- {
- clearAFK();
- }
- else if (id == ANIM_AGENT_STANDUP)
- {
- // send stand up command
- setControlFlags(AGENT_CONTROL_FINISH_ANIM);
- // now trigger dusting self off animation
- if (isAgentAvatarValid() && !gAgentAvatarp->mBelowWater && rand() % 3 == 0)
- sendAnimationRequest( ANIM_AGENT_BRUSH, ANIM_REQUEST_START );
- }
- else if (id == ANIM_AGENT_PRE_JUMP || id == ANIM_AGENT_LAND || id == ANIM_AGENT_MEDIUM_LAND)
- {
- setControlFlags(AGENT_CONTROL_FINISH_ANIM);
- }
- }
- bool LLAgent::isGodlike() const
- {
-