mirror of
https://foundry.openuru.org/gitblit/r/CWE-ou-minkata.git
synced 2025-07-21 04:39:45 +00:00
Hoist MOULOpenSourceClientPlugin/Plasma20/* to top level
to match H'uru layout and make patching/cherry-picking easier.
This commit is contained in:
850
Sources/Plasma/PubUtilLib/plAvatar/plAvatarTasks.cpp
Normal file
850
Sources/Plasma/PubUtilLib/plAvatar/plAvatarTasks.cpp
Normal file
@ -0,0 +1,850 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Additional permissions under GNU GPL version 3 section 7
|
||||
|
||||
If you modify this Program, or any covered work, by linking or
|
||||
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
|
||||
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
|
||||
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
|
||||
(or a modified version of those libraries),
|
||||
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
|
||||
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
|
||||
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
|
||||
licensors of this Program grant you additional
|
||||
permission to convey the resulting work. Corresponding Source for a
|
||||
non-source form of such a combination shall include the source code for
|
||||
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
|
||||
work.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
#include "hsConfig.h"
|
||||
#include "hsWindows.h"
|
||||
|
||||
// singular
|
||||
#include "plAvatarTasks.h"
|
||||
|
||||
// local
|
||||
#include "plArmatureMod.h"
|
||||
#include "plSeekPointMod.h"
|
||||
#include "plAvBrainHuman.h"
|
||||
#include "plAGAnim.h"
|
||||
#include "plAGAnimInstance.h"
|
||||
#include "plAGModifier.h"
|
||||
#include "plMatrixChannel.h"
|
||||
#include "plPhysicalControllerCore.h"
|
||||
#include "plAvatarMgr.h"
|
||||
|
||||
// global
|
||||
#include "hsUtils.h"
|
||||
|
||||
// other
|
||||
#include "plgDispatch.h"
|
||||
#include "../plMessage/plAvatarMsg.h"
|
||||
#include "../plMessage/plAnimCmdMsg.h"
|
||||
#include "../plMessage/plOneShotCallbacks.h"
|
||||
#include "../plMessage/plConsoleMsg.h"
|
||||
#include "../pnKeyedObject/plKey.h"
|
||||
#include "../pnSceneObject/plCoordinateInterface.h"
|
||||
#include "../plPipeline/plDebugText.h"
|
||||
#include "../plInputCore/plInputInterfaceMgr.h"
|
||||
#include "../plNetClient/plNetClientMgr.h"
|
||||
#include "../plNetCommon/plNetCommon.h"
|
||||
#include "../plMessage/plLinkToAgeMsg.h"
|
||||
#include "../pfMessage/pfKIMsg.h"
|
||||
|
||||
// for console hack
|
||||
hsBool plAvOneShotTask::fForce3rdPerson = true;
|
||||
#include "../pnMessage/plCameraMsg.h"
|
||||
|
||||
/////////////
|
||||
//
|
||||
// PLAVTASK
|
||||
// Abstract definition for the avatar task class
|
||||
//
|
||||
/////////////
|
||||
plAvTask::plAvTask()
|
||||
{
|
||||
}
|
||||
|
||||
// START
|
||||
hsBool plAvTask::Start(plArmatureMod *avatar, plArmatureBrain *brain, double time, hsScalar elapsed)
|
||||
{
|
||||
return true; // true indicates the task has started succesfully
|
||||
}
|
||||
|
||||
// PROCESS
|
||||
hsBool plAvTask::Process(plArmatureMod *avatar, plArmatureBrain *brain, double time, hsScalar elapsed)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Finish -----------------------------------------------------------------------------------
|
||||
// -------
|
||||
void plAvTask::Finish(plArmatureMod *avatar, plArmatureBrain *brain, double time, hsScalar elapsed)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
// DUMPDEBUG
|
||||
void plAvTask::DumpDebug(const char *name, int &x, int&y, int lineHeight, char *strBuf, plDebugText &debugTxt)
|
||||
{
|
||||
debugTxt.DrawString(x, y, "<anonymous task>");
|
||||
y += lineHeight;
|
||||
}
|
||||
|
||||
// READ
|
||||
void plAvTask::Read(hsStream *stream, hsResMgr *mgr)
|
||||
{
|
||||
plCreatable::Read(stream, mgr);
|
||||
}
|
||||
|
||||
// WRITE
|
||||
void plAvTask::Write(hsStream *stream, hsResMgr *mgr)
|
||||
{
|
||||
plCreatable::Write(stream, mgr);
|
||||
}
|
||||
|
||||
void plAvTask::ILimitPlayersInput(plArmatureMod *avatar)
|
||||
{
|
||||
// make sure this is the local avatar we are talking about
|
||||
if (avatar == plAvatarMgr::GetInstance()->GetLocalAvatar())
|
||||
{
|
||||
plInputInterfaceMgr::GetInstance()->ForceCursorHidden(true);
|
||||
// tell the KI to be disabled while we are busy
|
||||
pfKIMsg* msg = TRACKED_NEW pfKIMsg(pfKIMsg::kTempDisableKIandBB);
|
||||
plgDispatch::MsgSend( msg );
|
||||
}
|
||||
}
|
||||
|
||||
void plAvTask::IUndoLimitPlayersInput(plArmatureMod *avatar)
|
||||
{
|
||||
// make sure this is the local avatar we are talking about
|
||||
if (avatar == plAvatarMgr::GetInstance()->GetLocalAvatar())
|
||||
{
|
||||
plInputInterfaceMgr::GetInstance()->ForceCursorHidden(false);
|
||||
// tell the KI to be re-enabled
|
||||
pfKIMsg* msg = TRACKED_NEW pfKIMsg(pfKIMsg::kTempEnableKIandBB);
|
||||
plgDispatch::MsgSend( msg );
|
||||
}
|
||||
}
|
||||
|
||||
/////////////
|
||||
//
|
||||
// AVSEEKTASK
|
||||
//
|
||||
/////////////
|
||||
|
||||
// CTOR default
|
||||
plAvSeekTask::plAvSeekTask()
|
||||
: fAnimName(nil),
|
||||
fAlign(kAlignHandle),
|
||||
fDuration(0.25f),
|
||||
fTarget(nil),
|
||||
fAnimInstance(nil),
|
||||
fTargetTime(nil),
|
||||
fPhysicalAtStart(false),
|
||||
fCleanup(false)
|
||||
{
|
||||
}
|
||||
|
||||
// CTOR target, align, animName
|
||||
plAvSeekTask::plAvSeekTask(plKey target, plAvAlignment align, const char *animName)
|
||||
: fAlign(align),
|
||||
fDuration(0.25f),
|
||||
fTarget(target),
|
||||
fAnimInstance(nil),
|
||||
fTargetTime(nil),
|
||||
fPhysicalAtStart(false),
|
||||
fCleanup(false)
|
||||
{
|
||||
fAnimName = hsStrcpy(animName);
|
||||
}
|
||||
|
||||
// CTOR target
|
||||
plAvSeekTask::plAvSeekTask(plKey target)
|
||||
: fAnimName(nil),
|
||||
fAlign(kAlignHandle),
|
||||
fDuration(0.25f),
|
||||
fTarget(target),
|
||||
fAnimInstance(nil),
|
||||
fTargetTime(nil),
|
||||
fPhysicalAtStart(false),
|
||||
fCleanup(false)
|
||||
{
|
||||
}
|
||||
|
||||
void GetPositionAndRotation(hsMatrix44 transform, hsScalarTriple *position, hsQuat *rotation)
|
||||
{
|
||||
hsPoint3 p = (hsPoint3)transform.GetTranslate();
|
||||
position->fX = p.fX; position->fY = p.fY; position->fZ = p.fZ;
|
||||
|
||||
|
||||
transform.RemoveScale();
|
||||
|
||||
rotation->SetFromMatrix(&transform);
|
||||
rotation->Normalize();
|
||||
|
||||
float angle;
|
||||
hsVector3 axis;
|
||||
|
||||
rotation->GetAngleAxis(&angle, &axis);
|
||||
}
|
||||
|
||||
// START
|
||||
// Adjust our goal time based on our duration and the current time
|
||||
hsBool plAvSeekTask::Start(plArmatureMod *avatar, plArmatureBrain *brain, double time, hsScalar elapsed)
|
||||
{
|
||||
fTargetTime = time + fDuration; // clock starts now....
|
||||
fPhysicalAtStart = avatar->IsPhysicsEnabled();
|
||||
avatar->EnablePhysics(false); // always turn physics off for seek
|
||||
plAvBrainHuman *huBrain = plAvBrainHuman::ConvertNoRef(brain);
|
||||
if(huBrain)
|
||||
huBrain->IdleOnly();
|
||||
|
||||
ILimitPlayersInput(avatar);
|
||||
|
||||
if (!fTarget || !fTarget->ObjectIsLoaded())
|
||||
{
|
||||
fCleanup = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
plSceneObject* seekTarget = plSceneObject::ConvertNoRef(fTarget->ObjectIsLoaded());
|
||||
hsMatrix44 targetL2W = seekTarget->GetLocalToWorld();
|
||||
const plCoordinateInterface* subworldCI = nil;
|
||||
if (avatar->GetController())
|
||||
subworldCI = avatar->GetController()->GetSubworldCI();
|
||||
if (subworldCI)
|
||||
targetL2W = subworldCI->GetWorldToLocal() * targetL2W;
|
||||
|
||||
switch(fAlign)
|
||||
{
|
||||
// just match our handle to the target matrix
|
||||
case kAlignHandle:
|
||||
// targetL2Sim is already correct
|
||||
break;
|
||||
// match our handle to the target matrix at the end of the given animation
|
||||
case kAlignHandleAnimEnd:
|
||||
{
|
||||
hsMatrix44 adjustment;
|
||||
plAGAnim *anim = avatar->FindCustomAnim(fAnimName);
|
||||
GetStartToEndTransform(anim, nil, &adjustment, "Handle"); // actually getting end-to-start
|
||||
targetL2W = targetL2W * adjustment;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
|
||||
GetPositionAndRotation(targetL2W, &fTargetPosition, &fTargetRotation);
|
||||
Process(avatar, brain, time, elapsed);
|
||||
return true;
|
||||
}
|
||||
|
||||
// CALCHANDLETARGETPOSITION
|
||||
void CalcHandleTargetPosition(hsMatrix44 &result, plSceneObject *handle, plSceneObject *target, hsMatrix44 &bodyToHandle)
|
||||
{
|
||||
hsMatrix44 targetToWorld = target->GetLocalToWorld();
|
||||
|
||||
result = bodyToHandle * targetToWorld;
|
||||
}
|
||||
|
||||
// CALCHANDLETARGETPOSITION
|
||||
// where should I move my insertion point so that my bodyRoot lines up with the target?
|
||||
void CalcHandleTargetPosition(hsMatrix44 &result, plSceneObject *insert, plSceneObject *target, plSceneObject *bodyRoot)
|
||||
{
|
||||
hsMatrix44 bodyToHandle = bodyRoot->GetLocalToParent();
|
||||
CalcHandleTargetPosition(result, insert, target, bodyToHandle);
|
||||
}
|
||||
|
||||
// PROCESS
|
||||
// Move closer to the goal position and orientation
|
||||
hsBool plAvSeekTask::Process(plArmatureMod *avatar, plArmatureBrain *brain, double time, hsScalar elapsed)
|
||||
{
|
||||
hsQuat rotation;
|
||||
hsPoint3 position;
|
||||
avatar->GetPositionAndRotationSim(&position, &rotation);
|
||||
|
||||
// We've had a history of odd bugs caused by assuming a rotation quat is normalized.
|
||||
// This line here seems to be fixing one of them. (Avatars scaling oddly when smart seeking.)
|
||||
rotation.Normalize();
|
||||
|
||||
double timeToGo = fTargetTime - time - elapsed; // time from *beginning* of this interval to the goal
|
||||
if (fCleanup)
|
||||
{
|
||||
avatar->EnablePhysics( fPhysicalAtStart );
|
||||
IUndoLimitPlayersInput(avatar);
|
||||
|
||||
return false; // we're done processing
|
||||
}
|
||||
else if(timeToGo < .01)
|
||||
{
|
||||
fTargetRotation.Normalize();
|
||||
avatar->SetPositionAndRotationSim(&fTargetPosition, &fTargetRotation);
|
||||
fCleanup = true; // we're going to wait one frame for the transform to propagate
|
||||
return true; // still running until next frame/cleanup
|
||||
}
|
||||
else
|
||||
{
|
||||
hsPoint3 posToGo = fTargetPosition - position; // vec from here to the goal
|
||||
float thisPercentage = (float)(elapsed / timeToGo);
|
||||
|
||||
hsPoint3 newPosition = position + posToGo * thisPercentage;
|
||||
hsQuat newRotation;
|
||||
newRotation.SetFromSlerp(rotation, fTargetRotation, thisPercentage);
|
||||
|
||||
newRotation.Normalize();
|
||||
avatar->SetPositionAndRotationSim(&newPosition, &newRotation);
|
||||
return true; // we're still processing
|
||||
}
|
||||
}
|
||||
|
||||
void plAvSeekTask::LeaveAge(plArmatureMod *avatar)
|
||||
{
|
||||
fTarget = nil;
|
||||
fCleanup = true;
|
||||
}
|
||||
|
||||
///////////////////
|
||||
//
|
||||
// PLAVANIMTASK
|
||||
//
|
||||
///////////////////
|
||||
|
||||
// CTOR default
|
||||
plAvAnimTask::plAvAnimTask()
|
||||
: fAnimName(nil),
|
||||
fInitialBlend(0.0f),
|
||||
fTargetBlend(0.0f),
|
||||
fFadeSpeed(0.0f),
|
||||
fSetTime(0.0f),
|
||||
fStart(false),
|
||||
fLoop(false),
|
||||
fAttach(false),
|
||||
fAnimInstance(nil)
|
||||
{
|
||||
}
|
||||
|
||||
// CTOR animName, initialBlend, targetBlend, fadeSpeed, start, loop, attach
|
||||
plAvAnimTask::plAvAnimTask(const char *animName,
|
||||
hsScalar initialBlend,
|
||||
hsScalar targetBlend,
|
||||
hsScalar fadeSpeed,
|
||||
hsScalar setTime,
|
||||
hsBool start,
|
||||
hsBool loop,
|
||||
hsBool attach)
|
||||
: fInitialBlend(initialBlend),
|
||||
fTargetBlend(targetBlend),
|
||||
fFadeSpeed(fadeSpeed),
|
||||
fSetTime(setTime),
|
||||
fStart(start),
|
||||
fLoop(loop),
|
||||
fAttach(attach),
|
||||
fAnimInstance(nil)
|
||||
{
|
||||
if(animName)
|
||||
fAnimName = hsStrcpy(animName);
|
||||
}
|
||||
|
||||
// CTOR animName, fadeSpeed, attach
|
||||
plAvAnimTask::plAvAnimTask(const char *animName, hsScalar fadeSpeed, hsBool attach)
|
||||
: fInitialBlend(0.0f),
|
||||
fTargetBlend(0.0f),
|
||||
fFadeSpeed(fadeSpeed),
|
||||
fSetTime(0.0f),
|
||||
fStart(false),
|
||||
fLoop(false),
|
||||
fAttach(attach),
|
||||
fAnimInstance(nil)
|
||||
{
|
||||
if(animName)
|
||||
fAnimName = hsStrcpy(animName);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// DTOR
|
||||
plAvAnimTask::~plAvAnimTask()
|
||||
{
|
||||
if(fAnimName)
|
||||
{
|
||||
delete[] fAnimName;
|
||||
fAnimName = nil;
|
||||
}
|
||||
}
|
||||
|
||||
// START
|
||||
hsBool plAvAnimTask::Start(plArmatureMod *avatar, plArmatureBrain *brain, double time, hsScalar elapsed)
|
||||
{
|
||||
hsBool result = false;
|
||||
if(fAttach)
|
||||
{
|
||||
plAGAnimInstance * aInstance = avatar->FindOrAttachInstance(fAnimName, fInitialBlend);
|
||||
|
||||
if(aInstance)
|
||||
{
|
||||
if(fStart)
|
||||
aInstance->Start(fStart);
|
||||
if(fSetTime > 0)
|
||||
aInstance->SetCurrentTime(fSetTime, true);
|
||||
if(fTargetBlend > fInitialBlend)
|
||||
{
|
||||
aInstance->Fade(fTargetBlend, fFadeSpeed);
|
||||
}
|
||||
aInstance->SetLoop(fLoop);
|
||||
|
||||
result = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
hsStatusMessageF("Couldn't find animation <%s> for plAvAnimTask: will try again", fAnimName);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fAnimInstance = avatar->FindAnimInstance(fAnimName);
|
||||
if(fAnimInstance)
|
||||
{
|
||||
// start fading towards zero
|
||||
fAnimInstance->Fade(0.0, fFadeSpeed);
|
||||
}
|
||||
// if we started the fade, we're done and ready to process
|
||||
// if we couldn't find the animation, we're still done.
|
||||
result = true;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// PROCESS
|
||||
hsBool plAvAnimTask::Process(plArmatureMod *avatar, plArmatureBrain *brain, double time, hsScalar elapsed)
|
||||
{
|
||||
// the only reason we need this function is to watch the animation until it fades out
|
||||
hsBool result = false;
|
||||
if(fAttach)
|
||||
{
|
||||
// we finished in the Start() function
|
||||
}
|
||||
else
|
||||
{
|
||||
if(fAnimInstance)
|
||||
{
|
||||
if(fAnimInstance->GetBlend() < 0.1)
|
||||
{
|
||||
avatar->DetachAnimation(fAnimInstance);
|
||||
}
|
||||
else
|
||||
{
|
||||
// still waiting for the fadeout; keep the task alive
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// LEAVEAGE
|
||||
void plAvAnimTask::LeaveAge(plArmatureMod *avatar)
|
||||
{
|
||||
// if we are supposed to be removing the animation anyway, kill it completely on link out
|
||||
if (!fAttach)
|
||||
{
|
||||
fAnimInstance = avatar->FindAnimInstance(fAnimName);
|
||||
if(fAnimInstance)
|
||||
avatar->DetachAnimation(fAnimInstance);
|
||||
}
|
||||
}
|
||||
|
||||
// READ
|
||||
void plAvAnimTask::Read(hsStream *stream, hsResMgr *mgr)
|
||||
{
|
||||
fAnimName = stream->ReadSafeString();
|
||||
fInitialBlend = stream->ReadSwapScalar();
|
||||
fTargetBlend = stream->ReadSwapScalar();
|
||||
fFadeSpeed = stream->ReadSwapScalar();
|
||||
fSetTime = stream->ReadSwapScalar();
|
||||
fStart = stream->ReadBool();
|
||||
fLoop = stream->ReadBool();
|
||||
fAttach = stream->ReadBool();
|
||||
}
|
||||
|
||||
// WRITE
|
||||
void plAvAnimTask::Write(hsStream *stream, hsResMgr *mgr)
|
||||
{
|
||||
stream->WriteSafeString(fAnimName);
|
||||
stream->WriteSwapScalar(fInitialBlend);
|
||||
stream->WriteSwapScalar(fTargetBlend);
|
||||
stream->WriteSwapScalar(fFadeSpeed);
|
||||
stream->WriteSwapScalar(fSetTime);
|
||||
stream->WriteBool(fStart);
|
||||
stream->WriteBool(fLoop);
|
||||
stream->WriteBool(fAttach);
|
||||
}
|
||||
|
||||
////////////////
|
||||
//
|
||||
// AVONESHOTTASK
|
||||
// OBSOLETE -- DEPRECATED
|
||||
//
|
||||
////////////////
|
||||
|
||||
void plAvOneShotTask::InitDefaults()
|
||||
{
|
||||
fBackwards = false;
|
||||
fDisableLooping = false;
|
||||
fDisablePhysics = true;
|
||||
fAnimName = nil;
|
||||
fMoveHandle = false;
|
||||
fAnimInstance = nil;
|
||||
fDrivable = false;
|
||||
fReversible = false;
|
||||
fEnablePhysicsAtEnd = false;
|
||||
fDetachAnimation = false;
|
||||
fIgnore = false;
|
||||
fCallbacks = nil;
|
||||
fWaitFrames = 0;
|
||||
}
|
||||
|
||||
// CTOR default
|
||||
plAvOneShotTask::plAvOneShotTask()
|
||||
{
|
||||
InitDefaults();
|
||||
}
|
||||
|
||||
// CTOR (animName, drivable, reversible)
|
||||
// this construct is typically used when you want to create a one-shot task as part of a sequence
|
||||
// of tasks
|
||||
// it's different than the message-based constructor in that fDetachAnimation and fMoveHandle default to false
|
||||
plAvOneShotTask::plAvOneShotTask(const char *animName, hsBool drivable, hsBool reversible, plOneShotCallbacks *callbacks)
|
||||
{
|
||||
InitDefaults();
|
||||
|
||||
fDrivable = drivable;
|
||||
fReversible = reversible;
|
||||
fCallbacks = callbacks;
|
||||
|
||||
// we're going to use this sometime in the future, better ref it so someone else doesn't release it
|
||||
hsRefCnt_SafeRef(fCallbacks);
|
||||
fAnimName = hsStrcpy(animName);
|
||||
}
|
||||
|
||||
// CTOR (plAvOneShotMsg, plArmatureMod)
|
||||
// this constructor is typically used when we're doing a classic, isolated one-shot
|
||||
// fDetachAnimation and fMoveHandle both default to *true*
|
||||
plAvOneShotTask::plAvOneShotTask (plAvOneShotMsg *msg, plArmatureMod *avatar, plArmatureBrain *brain)
|
||||
{
|
||||
InitDefaults();
|
||||
|
||||
fDrivable = msg->fDrivable;
|
||||
fReversible = msg->fReversible;
|
||||
fCallbacks = msg->fCallbacks;
|
||||
fDetachAnimation = true;
|
||||
fMoveHandle = true;
|
||||
|
||||
// we're going to use this sometime in the future, better ref it so someone else doesn't release it
|
||||
hsRefCnt_SafeRef(fCallbacks);
|
||||
fAnimName = hsStrcpy(msg->fAnimName);
|
||||
}
|
||||
|
||||
// DTOR
|
||||
plAvOneShotTask::~plAvOneShotTask()
|
||||
{
|
||||
if(fAnimName)
|
||||
delete[] fAnimName;
|
||||
hsRefCnt_SafeUnRef(fCallbacks);
|
||||
}
|
||||
|
||||
|
||||
// START
|
||||
hsBool plAvOneShotTask::Start(plArmatureMod *avatar, plArmatureBrain *brain, double time, hsScalar elapsed)
|
||||
{
|
||||
hsBool result = false;
|
||||
|
||||
if (fIgnore)
|
||||
return true;
|
||||
|
||||
plAGMasterMod * master = avatar;
|
||||
|
||||
fAnimInstance = master->AttachAnimationBlended(fAnimName, 0);
|
||||
fDetachAnimation = true;
|
||||
|
||||
if(fAnimInstance)
|
||||
{
|
||||
fEnablePhysicsAtEnd = (avatar->IsPhysicsEnabled() && fDisablePhysics);
|
||||
if (fEnablePhysicsAtEnd)
|
||||
{
|
||||
// Must do the physics re-enable through a callback so that it happens before the "done" callback and we don't
|
||||
// step over some script's attempt to disable physics again.
|
||||
plAvatarPhysicsEnableCallbackMsg *epMsg = TRACKED_NEW plAvatarPhysicsEnableCallbackMsg(avatar->GetKey(), kStop, 0, 0, 0, 0);
|
||||
fAnimInstance->GetTimeConvert()->AddCallback(epMsg);
|
||||
hsRefCnt_SafeUnRef(epMsg);
|
||||
}
|
||||
|
||||
if (fCallbacks)
|
||||
{
|
||||
fAnimInstance->AttachCallbacks(fCallbacks);
|
||||
// ok, we're done with it, release it back to the river
|
||||
hsRefCnt_SafeUnRef(fCallbacks);
|
||||
fCallbacks = nil;
|
||||
}
|
||||
|
||||
fAnimInstance->SetBlend(1.0f);
|
||||
fAnimInstance->SetSpeed(1.0f);
|
||||
plAnimTimeConvert *atc = fAnimInstance->GetTimeConvert();
|
||||
if (fBackwards)
|
||||
atc->Backwards();
|
||||
if (fDisableLooping)
|
||||
atc->Loop(false);
|
||||
|
||||
fAnimInstance->SetCurrentTime(fBackwards ? atc->GetEnd() : atc->GetBegin(), true);
|
||||
fAnimInstance->Start(time);
|
||||
|
||||
fWaitFrames = 2; // wait two frames after animation finishes before finalizing
|
||||
|
||||
|
||||
if (fDisablePhysics)
|
||||
avatar->EnablePhysics(false);
|
||||
|
||||
ILimitPlayersInput(avatar);
|
||||
|
||||
// this is for a console command hack
|
||||
if (plAvOneShotTask::fForce3rdPerson && avatar->IsLocalAvatar())
|
||||
{
|
||||
// create message
|
||||
plCameraMsg* pMsg = TRACKED_NEW plCameraMsg;
|
||||
pMsg->SetBCastFlag(plMessage::kBCastByExactType);
|
||||
pMsg->SetBCastFlag(plMessage::kNetPropagate, false);
|
||||
pMsg->SetCmd(plCameraMsg::kResponderSetThirdPerson);
|
||||
plgDispatch::MsgSend( pMsg ); // whoosh... off it goes
|
||||
}
|
||||
|
||||
fMoveHandle = (fAnimInstance->GetAnimation()->GetChannel("Handle") != nil);
|
||||
if(fMoveHandle)
|
||||
{
|
||||
plMatrixDifferenceApp *differ = avatar->GetRootAnimator();
|
||||
differ->Reset(time); // throw away any old state
|
||||
differ->Enable(true);
|
||||
}
|
||||
|
||||
avatar->ApplyAnimations(time, elapsed);
|
||||
|
||||
result = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
char buf[256];
|
||||
sprintf(buf, "Oneshot: Can't find animation <%s>; all bets are off.", fAnimName);
|
||||
hsAssert(false, buf);
|
||||
result = true;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// PROCESS
|
||||
hsBool plAvOneShotTask::Process(plArmatureMod *avatar, plArmatureBrain *brain, double time, hsScalar elapsed)
|
||||
{
|
||||
// *** if we are under mouse control, adjust it here
|
||||
|
||||
avatar->ApplyAnimations(time, elapsed);
|
||||
if(fAnimInstance)
|
||||
{
|
||||
if(fAnimInstance->IsFinished())
|
||||
{
|
||||
const plAGAnim * animation = fAnimInstance->GetAnimation();
|
||||
double endTime = (fBackwards ? animation->GetStart() : animation->GetEnd());
|
||||
fAnimInstance->SetCurrentTime((hsScalar)endTime);
|
||||
avatar->ApplyAnimations(time, elapsed);
|
||||
|
||||
if(--fWaitFrames == 0)
|
||||
{
|
||||
|
||||
plSceneObject *handle = avatar->GetTarget(0);
|
||||
|
||||
avatar->DetachAnimation(fAnimInstance);
|
||||
avatar->GetRootAnimator()->Enable(false);
|
||||
plAvBrainHuman *humanBrain = plAvBrainHuman::ConvertNoRef(brain);
|
||||
if(fEnablePhysicsAtEnd)
|
||||
{
|
||||
#if 0//ndef PLASMA_EXTERNAL_RELEASE
|
||||
if (!humanBrain || humanBrain->fWalkingStrategy->HitGroundInThisAge())
|
||||
{
|
||||
// For some reason, calling CheckValidPosition at the beginning of
|
||||
// an age can cause detectors to incorrectly report collisions. So
|
||||
// we only call this if we're in the age.
|
||||
//
|
||||
// It's only debugging code anyway to help the artist check that
|
||||
// their oneshot doesn't end while penetrating geometry.
|
||||
char *overlaps = nil;
|
||||
if (avatar->GetPhysical())
|
||||
avatar->GetPhysical()->CheckValidPosition(&overlaps);
|
||||
if (overlaps)
|
||||
{
|
||||
char *buffy = TRACKED_NEW char[64 + strlen(overlaps)];
|
||||
sprintf(buffy, "Oneshot ends overlapping %s", overlaps);
|
||||
plConsoleMsg *showLine = TRACKED_NEW plConsoleMsg( plConsoleMsg::kAddLine, buffy );
|
||||
showLine->Send();
|
||||
delete[] overlaps;
|
||||
delete[] buffy;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if (humanBrain)
|
||||
humanBrain->ResetIdle();
|
||||
|
||||
IUndoLimitPlayersInput(avatar);
|
||||
// this is for a console command hack
|
||||
if (plAvOneShotTask::fForce3rdPerson && avatar->IsLocalAvatar())
|
||||
{
|
||||
// create message
|
||||
plCameraMsg* pMsg = TRACKED_NEW plCameraMsg;
|
||||
pMsg->SetBCastFlag(plMessage::kBCastByExactType);
|
||||
pMsg->SetBCastFlag(plMessage::kNetPropagate, false);
|
||||
pMsg->SetCmd(plCameraMsg::kResponderUndoThirdPerson);
|
||||
plgDispatch::MsgSend( pMsg ); // whoosh... off it goes
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
else
|
||||
return true; // still running; waiting for fWaitFrames == 0
|
||||
}
|
||||
else
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
void plAvOneShotTask::LeaveAge(plArmatureMod *avatar)
|
||||
{
|
||||
if (fAnimInstance)
|
||||
fAnimInstance->Stop();
|
||||
|
||||
if (fEnablePhysicsAtEnd)
|
||||
avatar->EnablePhysics(true);
|
||||
|
||||
IUndoLimitPlayersInput(avatar);
|
||||
fIgnore = true;
|
||||
}
|
||||
|
||||
void plAvOneShotTask::SetAnimName(char *name)
|
||||
{
|
||||
delete [] fAnimName;
|
||||
fAnimName = hsStrcpy(name);
|
||||
}
|
||||
|
||||
//////////////////////
|
||||
//
|
||||
// PLAVONESHOTLINKTASK
|
||||
//
|
||||
//////////////////////
|
||||
|
||||
plAvOneShotLinkTask::plAvOneShotLinkTask() : plAvOneShotTask(),
|
||||
fMarkerName(nil),
|
||||
fMarkerTime(-1),
|
||||
fStartTime(0),
|
||||
fLinkFired(false)
|
||||
{
|
||||
fDisablePhysics = false;
|
||||
}
|
||||
|
||||
plAvOneShotLinkTask::~plAvOneShotLinkTask()
|
||||
{
|
||||
delete [] fMarkerName;
|
||||
}
|
||||
|
||||
// task protocol
|
||||
hsBool plAvOneShotLinkTask::Start(plArmatureMod *avatar, plArmatureBrain *brain, double time, hsScalar elapsed)
|
||||
{
|
||||
hsBool result = plAvOneShotTask::Start(avatar, brain, time, elapsed);
|
||||
fStartTime = time;
|
||||
|
||||
if (fAnimInstance && fMarkerName)
|
||||
{
|
||||
const plATCAnim *anim = plATCAnim::ConvertNoRef(fAnimInstance->GetAnimation());
|
||||
if (anim)
|
||||
{
|
||||
// GetMarker returns -1 if the marker isn't found
|
||||
fMarkerTime = anim->GetMarker(fMarkerName);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
hsBool plAvOneShotLinkTask::Process(plArmatureMod *avatar, plArmatureBrain *brain, double time, hsScalar elapsed)
|
||||
{
|
||||
hsBool result = plAvOneShotTask::Process(avatar, brain, time, elapsed);
|
||||
if (fIgnore)
|
||||
return result;
|
||||
|
||||
if (avatar->GetTarget(0) == plNetClientApp::GetInstance()->GetLocalPlayer())
|
||||
{
|
||||
if (!fLinkFired && (fStartTime + fMarkerTime < time))
|
||||
{
|
||||
avatar->ILinkToPersonalAge();
|
||||
|
||||
avatar->EnablePhysics(false, plArmatureMod::kDisableReasonLinking);
|
||||
fLinkFired = true;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void plAvOneShotLinkTask::Write(hsStream *stream, hsResMgr *mgr)
|
||||
{
|
||||
plAvOneShotTask::Write(stream, mgr);
|
||||
stream->WriteSafeString(fAnimName);
|
||||
stream->WriteSafeString(fMarkerName);
|
||||
}
|
||||
|
||||
void plAvOneShotLinkTask::Read(hsStream *stream, hsResMgr *mgr)
|
||||
{
|
||||
plAvOneShotTask::Read(stream, mgr);
|
||||
fAnimName = stream->ReadSafeString();
|
||||
fMarkerName = stream->ReadSafeString();
|
||||
}
|
||||
|
||||
void plAvOneShotLinkTask::SetMarkerName(char *name)
|
||||
{
|
||||
delete [] fMarkerName;
|
||||
fMarkerName = hsStrcpy(name);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user