|
|
|
/*==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==*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
Some interesting special rules:
|
|
|
|
You can only transition from one animation to another at certain points.
|
|
|
|
|
|
|
|
The climb, mount, and dismount animations must be at their beginning or end
|
|
|
|
to transition.
|
|
|
|
|
|
|
|
If a climb or mount animation finishes and the key is not being held down, the idle
|
|
|
|
animation starts automatically.
|
|
|
|
|
|
|
|
If a climb or mount finishes and the key is being held down, the brain will *try*
|
|
|
|
to transition to the same stage, effectively looping it.
|
|
|
|
|
|
|
|
The idle can transition at any point.
|
|
|
|
|
|
|
|
The Release and FallOff aniamtions can forcibly transition *any* animation.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// INCLUDES
|
|
|
|
//
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
// singular
|
|
|
|
#include "plAvBrainClimb.h"
|
|
|
|
|
|
|
|
// local
|
|
|
|
#include "plAnimStage.h"
|
|
|
|
#include "plAGAnim.h"
|
|
|
|
#include "plAGAnimInstance.h"
|
|
|
|
#include "plArmatureMod.h"
|
|
|
|
#include "plMatrixChannel.h"
|
|
|
|
#include "plAvBrainHuman.h"
|
|
|
|
|
|
|
|
// global
|
|
|
|
#include "hsTimer.h"
|
|
|
|
|
|
|
|
// other
|
|
|
|
#include "plPipeline/plDebugText.h"
|
|
|
|
#include "plMessage/plSimStateMsg.h"
|
|
|
|
#include "plMessage/plLOSHitMsg.h"
|
|
|
|
#include "plMessage/plLOSRequestMsg.h"
|
|
|
|
#include "plMessage/plClimbEventMsg.h"
|
|
|
|
#include "pnNetCommon/plSDLTypes.h"
|
|
|
|
|
|
|
|
#include "plSDL/plSDL.h"
|
|
|
|
#include "plAvatarSDLModifier.h"
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// IMPLEMENTATION
|
|
|
|
//
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
// CTOR default
|
|
|
|
plAvBrainClimb::plAvBrainClimb()
|
|
|
|
: fCurMode(kInactive),
|
|
|
|
fNextMode(kInactive),
|
|
|
|
fDesiredDirection(plClimbMsg::kUp),
|
|
|
|
fControlDir(0.0f),
|
|
|
|
|
|
|
|
fAllowedDirections(plClimbMsg::kUp | plClimbMsg::kDown | plClimbMsg::kLeft | plClimbMsg::kRight),
|
|
|
|
fPhysicallyBlockedDirections(0),
|
|
|
|
fOldPhysicallyBlockedDirections(0),
|
|
|
|
fAllowedDismounts(0),
|
|
|
|
|
|
|
|
fCurStage(nil),
|
|
|
|
fExitStage(nil),
|
|
|
|
fVerticalProbeLength(0.0f),
|
|
|
|
fHorizontalProbeLength(0.0f),
|
|
|
|
|
|
|
|
fUp(nil),
|
|
|
|
fDown(nil),
|
|
|
|
fLeft(nil),
|
|
|
|
fRight(nil),
|
|
|
|
fMountUp(nil),
|
|
|
|
fMountDown(nil),
|
|
|
|
fMountLeft(nil),
|
|
|
|
fMountRight(nil),
|
|
|
|
fDismountUp(nil),
|
|
|
|
fDismountDown(nil),
|
|
|
|
fDismountLeft(nil),
|
|
|
|
fDismountRight(nil),
|
|
|
|
fIdle(nil),
|
|
|
|
fRelease(nil),
|
|
|
|
fFallOff(nil)
|
|
|
|
{
|
|
|
|
IInitAnimations();
|
|
|
|
}
|
|
|
|
|
|
|
|
// PLAVBRAINCLIMB
|
|
|
|
plAvBrainClimb::plAvBrainClimb(Mode nextMode)
|
|
|
|
: fCurMode(kInactive),
|
|
|
|
fNextMode(nextMode),
|
|
|
|
fDesiredDirection(plClimbMsg::kUp),
|
|
|
|
fControlDir(0.0f),
|
|
|
|
|
|
|
|
fAllowedDirections(plClimbMsg::kUp | plClimbMsg::kDown | plClimbMsg::kLeft | plClimbMsg::kRight),
|
|
|
|
fPhysicallyBlockedDirections(0),
|
|
|
|
fOldPhysicallyBlockedDirections(0),
|
|
|
|
fAllowedDismounts(0),
|
|
|
|
|
|
|
|
fCurStage(nil),
|
|
|
|
fExitStage(nil),
|
|
|
|
fVerticalProbeLength(0.0f),
|
|
|
|
fHorizontalProbeLength(0.0f),
|
|
|
|
|
|
|
|
fUp(nil),
|
|
|
|
fDown(nil),
|
|
|
|
fLeft(nil),
|
|
|
|
fRight(nil),
|
|
|
|
fMountUp(nil),
|
|
|
|
fMountDown(nil),
|
|
|
|
fMountLeft(nil),
|
|
|
|
fMountRight(nil),
|
|
|
|
fDismountUp(nil),
|
|
|
|
fDismountDown(nil),
|
|
|
|
fDismountLeft(nil),
|
|
|
|
fDismountRight(nil),
|
|
|
|
fIdle(nil),
|
|
|
|
fRelease(nil),
|
|
|
|
fFallOff(nil)
|
|
|
|
{
|
|
|
|
IInitAnimations();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
plAvBrainClimb::~plAvBrainClimb()
|
|
|
|
{
|
|
|
|
if(fAvMod)
|
|
|
|
{
|
|
|
|
if(fCurStage)
|
|
|
|
fCurStage->Detach(fAvMod);
|
|
|
|
if(fExitStage)
|
|
|
|
fExitStage->Detach(fAvMod);
|
|
|
|
}
|
|
|
|
if(fUp) delete fUp;
|
|
|
|
if(fDown) delete fDown;
|
|
|
|
if(fLeft) delete fLeft;
|
|
|
|
if(fRight) delete fRight;
|
|
|
|
if(fMountUp) delete fMountUp;
|
|
|
|
if(fMountDown) delete fMountDown;
|
|
|
|
if(fMountLeft) delete fMountLeft;
|
|
|
|
if(fMountRight) delete fMountRight;
|
|
|
|
if(fDismountUp) delete fDismountUp;
|
|
|
|
if(fDismountLeft) delete fDismountLeft;
|
|
|
|
if(fDismountRight) delete fDismountRight;
|
|
|
|
if(fIdle) delete fIdle;
|
|
|
|
// if(fRelease) delete fRelease;
|
|
|
|
// if(fFallOff) delete fFallOff;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ACTIVATE
|
|
|
|
void plAvBrainClimb::Activate(plArmatureModBase *avMod)
|
|
|
|
{
|
|
|
|
plArmatureBrain::Activate(avMod);
|
|
|
|
ICalcProbeLengths();
|
|
|
|
|
|
|
|
fAvMod->GetRootAnimator()->Enable(true);
|
|
|
|
fAvMod->EnablePhysicsKinematic(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
void plAvBrainClimb::Deactivate()
|
|
|
|
{
|
|
|
|
fAvMod->GetRootAnimator()->Enable(false);
|
|
|
|
fAvMod->EnablePhysicsKinematic(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
// APPLY
|
|
|
|
bool plAvBrainClimb::Apply(double time, float elapsed)
|
|
|
|
{
|
|
|
|
bool result = true;
|
|
|
|
|
|
|
|
IGetDesiredDirection();
|
|
|
|
|
|
|
|
float overage = 0.0f; // if we ran past the end of the current stage, remember how much
|
|
|
|
bool done = false;
|
|
|
|
|
|
|
|
if(fExitStage)
|
|
|
|
done = IProcessExitStage(time, elapsed);
|
|
|
|
else
|
|
|
|
done = IAdvanceCurrentStage(time, elapsed, overage);
|
|
|
|
|
|
|
|
if(done || fCurMode == kIdle)
|
|
|
|
{
|
|
|
|
// if the transition is to one of the terminal modes, we're going to abort
|
|
|
|
result = ITryStageTransition(time, overage);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!result && fExitStage)
|
|
|
|
{
|
|
|
|
fExitStage->Detach(fAvMod);
|
|
|
|
}
|
|
|
|
|
|
|
|
fAvMod->ApplyAnimations(time, elapsed);
|
|
|
|
|
|
|
|
IProbeEnvironment();
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
// MSGRECEIVE
|
|
|
|
bool plAvBrainClimb::MsgReceive(plMessage *msg)
|
|
|
|
{
|
|
|
|
plClimbMsg* climbMsg = plClimbMsg::ConvertNoRef(msg);
|
|
|
|
if (climbMsg)
|
|
|
|
{
|
|
|
|
return IHandleClimbMsg(climbMsg);
|
|
|
|
}
|
|
|
|
|
|
|
|
plLOSHitMsg *losMsg = plLOSHitMsg::ConvertNoRef(msg);
|
|
|
|
if (losMsg)
|
|
|
|
{
|
|
|
|
return IHandleLOSMsg(losMsg);
|
|
|
|
}
|
|
|
|
|
|
|
|
return plArmatureBrain::MsgReceive(msg);
|
|
|
|
}
|
|
|
|
|
|
|
|
// IHANDLECLIMBMSG
|
|
|
|
bool plAvBrainClimb::IHandleClimbMsg(plClimbMsg *msg)
|
|
|
|
{
|
|
|
|
switch(msg->fCommand)
|
|
|
|
{
|
|
|
|
case plClimbMsg::kEnableClimb:
|
|
|
|
if(msg->fStatus)
|
|
|
|
this->fAllowedDirections |= msg->fDirection;
|
|
|
|
else
|
|
|
|
this->fAllowedDirections &= ~msg->fDirection;
|
|
|
|
break;
|
|
|
|
case plClimbMsg::kEnableDismount:
|
|
|
|
if(msg->fStatus)
|
|
|
|
this->fAllowedDismounts |= msg->fDirection;
|
|
|
|
else
|
|
|
|
this->fAllowedDismounts &= ~msg->fDirection;
|
|
|
|
break;
|
|
|
|
case plClimbMsg::kRelease:
|
|
|
|
IRelease(true);
|
|
|
|
break;
|
|
|
|
case plClimbMsg::kFallOff:
|
|
|
|
{
|
|
|
|
if(fCurMode != kReleasing
|
|
|
|
&& fCurMode != kFallingOff
|
|
|
|
&& fCurMode != kFinishing)
|
|
|
|
{
|
|
|
|
plClimbEventMsg* pMsg = new plClimbEventMsg;
|
|
|
|
pMsg->SetSender(msg->fTarget);
|
|
|
|
pMsg->SetBCastFlag(plMessage::kBCastByExactType);
|
|
|
|
pMsg->SetBCastFlag(plMessage::kLocalPropagate);
|
|
|
|
pMsg->SetBCastFlag(plMessage::kNetPropagate);
|
|
|
|
pMsg->SetBCastFlag(plMessage::kNetForce);
|
|
|
|
pMsg->Send();
|
|
|
|
}
|
|
|
|
IRelease(false);
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// IHANDLELOSMSG
|
|
|
|
bool plAvBrainClimb::IHandleLOSMsg(plLOSHitMsg *msg)
|
|
|
|
{
|
|
|
|
plClimbMsg::Direction blockDir = static_cast<plClimbMsg::Direction>(msg->fRequestID);
|
|
|
|
// this is a weak test because someone else could be using the same bits to mean something different
|
|
|
|
// the real strategy is that we should only receive LOS messages of our own creation
|
|
|
|
bool oneOfOurs = blockDir == plClimbMsg::kUp || blockDir == plClimbMsg::kDown || blockDir == plClimbMsg::kLeft || blockDir == plClimbMsg::kRight;
|
|
|
|
if(oneOfOurs)
|
|
|
|
{
|
|
|
|
fPhysicallyBlockedDirections |= blockDir;
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// IPROCESSEXITSTAGE
|
|
|
|
bool plAvBrainClimb::IProcessExitStage(double time, float elapsed)
|
|
|
|
{
|
|
|
|
plAGAnimInstance *ai = fExitStage->GetAnimInstance();
|
|
|
|
bool animDone = ai->IsAtEnd();
|
|
|
|
float unused;
|
|
|
|
|
|
|
|
// if we have an exit stage running, move it instead of the base stage
|
|
|
|
if(!animDone)
|
|
|
|
fExitStage->MoveRelative(time, elapsed, unused, fAvMod); // only advance if it's not finished yet
|
|
|
|
|
|
|
|
float curBlend = ai->GetBlend();
|
|
|
|
|
|
|
|
if(curBlend > .99) // reached peak strength
|
|
|
|
{
|
|
|
|
fCurStage->Detach(fAvMod); // remove the (now completely masked) underlying anim
|
|
|
|
fCurStage = nil;
|
|
|
|
ai->Fade(0, 2.0f); // start fading the exit anim
|
|
|
|
} else if(animDone && curBlend == 0.0f) {
|
|
|
|
return true; // finished and faded; we're really done now
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// IRELEASE
|
|
|
|
void plAvBrainClimb::IRelease(bool intentional)
|
|
|
|
{
|
|
|
|
if(fCurMode != kReleasing
|
|
|
|
&& fCurMode != kFallingOff
|
|
|
|
&& fCurMode != kFinishing)
|
|
|
|
{
|
|
|
|
if(intentional)
|
|
|
|
{
|
|
|
|
// fNextMode = kReleasing;
|
|
|
|
fCurMode = kReleasing;
|
|
|
|
fExitStage = fRelease;
|
|
|
|
} else {
|
|
|
|
// fNextMode = kFallingOff;
|
|
|
|
fCurMode = kFallingOff;
|
|
|
|
fExitStage = fFallOff;
|
|
|
|
}
|
|
|
|
fNextMode = kFinishing;
|
|
|
|
double time = hsTimer::GetSysSeconds();
|
|
|
|
// attach the exit stage atop the current stage. from here on out we'll only advance
|
|
|
|
// the current stage.
|
|
|
|
fAvMod->GetRootAnimator()->Enable(false);
|
|
|
|
fAvMod->EnablePhysicsKinematic(false);
|
|
|
|
fExitStage->Attach(fAvMod, this, 1.0f, time);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// IADVANCECURRENTSTAGE
|
|
|
|
bool plAvBrainClimb::IAdvanceCurrentStage(double time, float elapsed, float &overage)
|
|
|
|
{
|
|
|
|
bool stageDone = false;
|
|
|
|
if(fCurStage)
|
|
|
|
{
|
|
|
|
// elapsed tells us how far in time to move the animation
|
|
|
|
// we must combine it with the key state to figure out whether
|
|
|
|
// we're moving forward or backward in the animation
|
|
|
|
fControlDir = 0.0f; // 0 is still; -1 is backwards; 1 is forwards
|
|
|
|
|
|
|
|
switch(fCurMode)
|
|
|
|
{
|
|
|
|
case kDismountingUp: // if dismounting or mounting become reversable, move
|
|
|
|
case kMountingUp: // these cases to be with "kClimbingUp"; same for the rest
|
|
|
|
case kDismountingRight:
|
|
|
|
case kMountingRight:
|
|
|
|
case kDismountingDown:
|
|
|
|
case kMountingDown:
|
|
|
|
case kDismountingLeft:
|
|
|
|
case kMountingLeft:
|
|
|
|
case kFallingOff:
|
|
|
|
case kReleasing:
|
|
|
|
case kFinishing:
|
|
|
|
case kIdle:
|
|
|
|
case kClimbingUp:
|
|
|
|
case kClimbingRight:
|
|
|
|
case kClimbingDown:
|
|
|
|
case kClimbingLeft:
|
|
|
|
fControlDir = 1.0f; // these guys all auto-advance
|
|
|
|
break;
|
|
|
|
case kInactive:
|
|
|
|
case kUnknown:
|
|
|
|
// fControlDir is already 0
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
hsStatusMessage("Unknown mode in plAvBrainClimb::IAdvanceCurrentStage");
|
|
|
|
}
|
|
|
|
float delta = elapsed * fControlDir;
|
|
|
|
stageDone = fCurStage->MoveRelative(time, delta, overage, fAvMod);
|
|
|
|
} else {
|
|
|
|
stageDone = true;
|
|
|
|
}
|
|
|
|
return stageDone;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ITRYSTAGETRANSITION
|
|
|
|
bool plAvBrainClimb::ITryStageTransition(double time, float overage)
|
|
|
|
{
|
|
|
|
// hsStatusMessageF("Got overage %f", overage);
|
|
|
|
IChooseNextMode();
|
|
|
|
|
|
|
|
bool result = true;
|
|
|
|
// and vice versa
|
|
|
|
if(fCurStage && fCurStage != fIdle)
|
|
|
|
{
|
|
|
|
hsStatusMessage("Wrapping externally.");
|
|
|
|
bool atStart = overage >= 0.0f ? true : false; // if we went off the end, back to start
|
|
|
|
fCurStage->Reset(time, fAvMod, atStart);
|
|
|
|
// any time we start a stage besides idle, clear the climbing and dismount restrictions
|
|
|
|
// this->fAllowedDirections = plClimbMsg::kUp | plClimbMsg::kDown | plClimbMsg::kLeft | plClimbMsg::kRight;
|
|
|
|
// this->fAllowedDismounts = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(fNextMode != fCurMode)
|
|
|
|
{
|
|
|
|
if(fCurStage)
|
|
|
|
fCurStage->Detach(fAvMod);
|
|
|
|
fCurStage = IGetStageFromMode(fNextMode);
|
|
|
|
if(fCurStage)
|
|
|
|
{
|
|
|
|
hsAssert(fCurStage, "Couldn't get next stage - mode has no stage. (Matt)");
|
|
|
|
fCurMode = fNextMode;
|
|
|
|
if(fCurStage)
|
|
|
|
result = (fCurStage->Attach(fAvMod, this, 1.0f, time) != nil);
|
|
|
|
fAvMod->DirtySynchState(kSDLAvatar, 0); // write our new stage to the server
|
|
|
|
} else {
|
|
|
|
result = false;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// hsStatusMessage("Wrapping externally.");
|
|
|
|
// bool atStart = overage >= 0.0f ? true : false; // if we went off the end, back to start
|
|
|
|
// // and vice versa
|
|
|
|
// if(fCurStage)
|
|
|
|
// fCurStage->Reset(time, fAvMod, atStart);
|
|
|
|
}
|
|
|
|
|
|
|
|
fNextMode = kUnknown;
|
|
|
|
|
|
|
|
if(fCurStage)
|
|
|
|
{
|
|
|
|
if(overage < 0.0f)
|
|
|
|
{
|
|
|
|
float length = fCurStage->GetLength();
|
|
|
|
fCurStage->SetLocalTime(length + overage);
|
|
|
|
} else {
|
|
|
|
fCurStage->SetLocalTime(overage);
|
|
|
|
}
|
|
|
|
fAvMod->GetRootAnimator()->Reset(time);
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ICHOOSENEXTMODE
|
|
|
|
bool plAvBrainClimb::IChooseNextMode()
|
|
|
|
{
|
|
|
|
// bear in mind this is only called when we're at a point where
|
|
|
|
// we can change direction (usually because a climb loop has
|
|
|
|
// just finished)
|
|
|
|
switch (fCurMode)
|
|
|
|
{
|
|
|
|
case kInactive:
|
|
|
|
case kUnknown:
|
|
|
|
case kFinishing:
|
|
|
|
break; // no change
|
|
|
|
|
|
|
|
case kDismountingUp:
|
|
|
|
case kDismountingDown:
|
|
|
|
case kDismountingLeft:
|
|
|
|
case kDismountingRight:
|
|
|
|
case kFallingOff:
|
|
|
|
case kReleasing:
|
|
|
|
fNextMode = kFinishing;
|
|
|
|
break;
|
|
|
|
case kMountingUp:
|
|
|
|
case kClimbingUp:
|
|
|
|
case kMountingDown:
|
|
|
|
case kClimbingDown:
|
|
|
|
case kMountingLeft:
|
|
|
|
case kClimbingLeft:
|
|
|
|
case kMountingRight:
|
|
|
|
case kClimbingRight:
|
|
|
|
case kIdle:
|
|
|
|
fNextMode = kIdle;
|
|
|
|
if(fAllowedDismounts & fDesiredDirection)
|
|
|
|
{
|
|
|
|
switch(fDesiredDirection)
|
|
|
|
{
|
|
|
|
case plClimbMsg::kUp:
|
|
|
|
fNextMode = kDismountingUp;
|
|
|
|
break;
|
|
|
|
case plClimbMsg::kDown:
|
|
|
|
fNextMode = kDismountingDown;
|
|
|
|
break;
|
|
|
|
case plClimbMsg::kLeft:
|
|
|
|
fNextMode = kDismountingLeft;
|
|
|
|
break;
|
|
|
|
case plClimbMsg::kRight:
|
|
|
|
fNextMode = kDismountingRight;
|
|
|
|
break;
|
|
|
|
case plClimbMsg::kCenter:
|
|
|
|
fNextMode = kIdle;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
hsAssert(false, "Error in fDesiredDirection. (Matt)");
|
|
|
|
}
|
|
|
|
} else if(fAllowedDirections & fDesiredDirection & ~fPhysicallyBlockedDirections)
|
|
|
|
{
|
|
|
|
switch(fDesiredDirection)
|
|
|
|
{
|
|
|
|
case plClimbMsg::kUp:
|
|
|
|
fNextMode = kClimbingUp;
|
|
|
|
break;
|
|
|
|
case plClimbMsg::kDown:
|
|
|
|
fNextMode = kClimbingDown;
|
|
|
|
break;
|
|
|
|
case plClimbMsg::kLeft:
|
|
|
|
fNextMode = kClimbingLeft;
|
|
|
|
break;
|
|
|
|
case plClimbMsg::kRight:
|
|
|
|
fNextMode = kClimbingRight;
|
|
|
|
break;
|
|
|
|
case plClimbMsg::kCenter:
|
|
|
|
fNextMode = kIdle;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
hsAssert(false, "Error in fDesiredDirection. (Matt)");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
hsAssert(false, "Error in fCurMode. (Matt)");
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// IGETSTAGE
|
|
|
|
plAnimStage * plAvBrainClimb::IGetStageFromMode(Mode mode)
|
|
|
|
{
|
|
|
|
switch(mode)
|
|
|
|
{
|
|
|
|
case kClimbingUp:
|
|
|
|
return fUp;
|
|
|
|
case kClimbingDown:
|
|
|
|
return fDown;
|
|
|
|
case kClimbingLeft:
|
|
|
|
return fLeft;
|
|
|
|
case kClimbingRight:
|
|
|
|
return fRight;
|
|
|
|
case kMountingUp:
|
|
|
|
return fMountUp;
|
|
|
|
case kMountingDown:
|
|
|
|
return fMountDown;
|
|
|
|
case kMountingLeft:
|
|
|
|
return fMountLeft;
|
|
|
|
case kMountingRight:
|
|
|
|
return fMountRight;
|
|
|
|
case kDismountingUp:
|
|
|
|
return fDismountUp;
|
|
|
|
case kDismountingDown:
|
|
|
|
return fDismountDown;
|
|
|
|
case kDismountingLeft:
|
|
|
|
return fDismountLeft;
|
|
|
|
case kDismountingRight:
|
|
|
|
return fDismountRight;
|
|
|
|
case kIdle:
|
|
|
|
return fIdle;
|
|
|
|
case kReleasing:
|
|
|
|
return fRelease;
|
|
|
|
case kFallingOff:
|
|
|
|
return fFallOff;
|
|
|
|
case kInactive:
|
|
|
|
case kFinishing:
|
|
|
|
case kUnknown:
|
|
|
|
case kDone:
|
|
|
|
return nil;
|
|
|
|
default:
|
|
|
|
hsAssert(false, "Unknown mode.");
|
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
plAvBrainClimb::Mode plAvBrainClimb::IGetModeFromStage(plAnimStage *stage)
|
|
|
|
{
|
|
|
|
if(stage == fUp)
|
|
|
|
return kClimbingUp;
|
|
|
|
else if(stage == fDown)
|
|
|
|
return kClimbingDown;
|
|
|
|
else if(stage == fLeft)
|
|
|
|
return kClimbingLeft;
|
|
|
|
else if(stage == fRight)
|
|
|
|
return kClimbingRight;
|
|
|
|
else if(stage == fMountUp)
|
|
|
|
return kMountingUp;
|
|
|
|
else if(stage == fMountDown)
|
|
|
|
return kMountingDown;
|
|
|
|
else if(stage == fMountLeft)
|
|
|
|
return kMountingLeft;
|
|
|
|
else if(stage == fMountRight)
|
|
|
|
return kMountingRight;
|
|
|
|
else if(stage == fDismountUp)
|
|
|
|
return kDismountingUp;
|
|
|
|
else if(stage == fDismountDown)
|
|
|
|
return kDismountingDown;
|
|
|
|
else if(stage == fDismountLeft)
|
|
|
|
return kDismountingLeft;
|
|
|
|
else if(stage == fDismountRight)
|
|
|
|
return kDismountingRight;
|
|
|
|
else if(stage == fIdle)
|
|
|
|
return kIdle;
|
|
|
|
else if(stage == fRelease)
|
|
|
|
return kReleasing;
|
|
|
|
else if(stage == fFallOff)
|
|
|
|
return kFallingOff;
|
|
|
|
else
|
|
|
|
return kUnknown;
|
|
|
|
}
|
|
|
|
|
|
|
|
// IGETDESIREDDIRECTION
|
|
|
|
void plAvBrainClimb::IGetDesiredDirection()
|
|
|
|
{
|
|
|
|
if(fAvMod->ForwardKeyDown()) {
|
|
|
|
fDesiredDirection = plClimbMsg::kUp;
|
|
|
|
} else if (fAvMod->BackwardKeyDown()) {
|
|
|
|
fDesiredDirection = plClimbMsg::kDown;
|
|
|
|
} else if (fAvMod->TurnLeftKeyDown()) {
|
|
|
|
fDesiredDirection = plClimbMsg::kLeft;
|
|
|
|
} else if (fAvMod->TurnRightKeyDown()) {
|
|
|
|
fDesiredDirection = plClimbMsg::kRight;
|
|
|
|
} else {
|
|
|
|
fDesiredDirection = plClimbMsg::kCenter;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Look left, right, up, and down to see which directions are clear
|
|
|
|
for our movement. We could do this by positioning our actual collision
|
|
|
|
body and testing for hits, but it gives a lot more false positives *and*
|
|
|
|
we won't get the normals of intersection, so it will be more complex
|
|
|
|
to figure out which directions are actually blocked.
|
|
|
|
The approach here is to do a raycast in the aforementioned directions
|
|
|
|
and fail that direction if the raycast hits anything. */
|
|
|
|
void plAvBrainClimb::IProbeEnvironment()
|
|
|
|
{
|
|
|
|
hsMatrix44 l2w = fAvMod->GetTarget(0)->GetLocalToWorld();
|
|
|
|
// we're just going to pull the axes out of the
|
|
|
|
|
|
|
|
hsPoint3 up = hsPoint3(l2w.GetAxis(hsMatrix44::kUp) * fVerticalProbeLength);
|
|
|
|
hsPoint3 down = -up;
|
|
|
|
hsPoint3 right = hsPoint3(l2w.GetAxis(hsMatrix44::kRight) * fHorizontalProbeLength);
|
|
|
|
hsPoint3 left = -right;
|
|
|
|
hsPoint3 start = l2w.GetTranslate();
|
|
|
|
|
|
|
|
start.fZ += 3.0f; // move the origin from the feet to the bellybutton
|
|
|
|
up += start;
|
|
|
|
down += start;
|
|
|
|
left += start;
|
|
|
|
right += start;
|
|
|
|
|
|
|
|
plKey ourKey = fAvMod->GetKey();
|
|
|
|
|
|
|
|
// *** would be cool if we could hint that these should be batched for spatial coherence optimization
|
|
|
|
plLOSRequestMsg *upReq = new plLOSRequestMsg(ourKey, start, up, plSimDefs::kLOSDBCustom, plLOSRequestMsg::kTestAny, plLOSRequestMsg::kReportHit);
|
|
|
|
upReq->SetRequestID(static_cast<uint32_t>(plClimbMsg::kUp));
|
|
|
|
upReq->Send();
|
|
|
|
|
|
|
|
plLOSRequestMsg *downReq = new plLOSRequestMsg(ourKey, start, down, plSimDefs::kLOSDBCustom, plLOSRequestMsg::kTestAny, plLOSRequestMsg::kReportHit);
|
|
|
|
downReq->SetRequestID(static_cast<uint32_t>(plClimbMsg::kDown));
|
|
|
|
downReq->Send();
|
|
|
|
|
|
|
|
plLOSRequestMsg *leftReq = new plLOSRequestMsg(ourKey, start, left, plSimDefs::kLOSDBCustom, plLOSRequestMsg::kTestAny, plLOSRequestMsg::kReportHit);
|
|
|
|
leftReq->SetRequestID(static_cast<uint32_t>(plClimbMsg::kLeft));
|
|
|
|
leftReq->SetRequestType(plSimDefs::kLOSDBCustom);
|
|
|
|
leftReq->Send();
|
|
|
|
|
|
|
|
plLOSRequestMsg *rightReq = new plLOSRequestMsg(ourKey, start, right, plSimDefs::kLOSDBCustom, plLOSRequestMsg::kTestAny, plLOSRequestMsg::kReportHit);
|
|
|
|
rightReq->SetRequestID(static_cast<uint32_t>(plClimbMsg::kRight));
|
|
|
|
rightReq->Send();
|
|
|
|
|
|
|
|
fOldPhysicallyBlockedDirections = fPhysicallyBlockedDirections;
|
|
|
|
fPhysicallyBlockedDirections = 0; // clear our blocks until the new reports come in....
|
|
|
|
}
|
|
|
|
|
|
|
|
// ICalcProbeLengths -------------------
|
|
|
|
// -----------------
|
|
|
|
void plAvBrainClimb::ICalcProbeLengths()
|
|
|
|
{
|
|
|
|
// we assume that the up and down climbs go the same distance;
|
|
|
|
// same for the left and right climbs
|
|
|
|
plAGAnim *up = fAvMod->FindCustomAnim("ClimbUp");
|
|
|
|
plAGAnim *left = fAvMod->FindCustomAnim("ClimbLeft");
|
|
|
|
|
|
|
|
hsMatrix44 upMove, leftMove;
|
|
|
|
|
|
|
|
hsAssert(up, "Couldn't find ClimbUp animation.");
|
|
|
|
if(up)
|
|
|
|
{
|
|
|
|
GetStartToEndTransform(up, &upMove, nil, "Handle");
|
|
|
|
fVerticalProbeLength = upMove.GetTranslate().fZ;
|
|
|
|
} else
|
|
|
|
fVerticalProbeLength = 4.0f; // guess
|
|
|
|
|
|
|
|
hsAssert(left, "Couldn't find ClimbLeft animation.");
|
|
|
|
if(left)
|
|
|
|
{
|
|
|
|
GetStartToEndTransform(left, &leftMove, nil, "Handle");
|
|
|
|
fHorizontalProbeLength = leftMove.GetTranslate().fX;
|
|
|
|
} else
|
|
|
|
fHorizontalProbeLength = 3.0f; // guess
|
|
|
|
}
|
|
|
|
|
|
|
|
// IInitAnimations ---------------------
|
|
|
|
// ---------------
|
|
|
|
bool plAvBrainClimb::IInitAnimations()
|
|
|
|
{
|
|
|
|
fUp = new plAnimStage("WallClimbUp",
|
|
|
|
plAnimStage::kNotifyEnter, plAnimStage::kForwardAuto, plAnimStage::kBackNone, plAnimStage::kAdvanceAuto, plAnimStage::kRegressAuto,
|
|
|
|
0);
|
|
|
|
fDown = new plAnimStage("WallClimbDown",
|
|
|
|
plAnimStage::kNotifyEnter, plAnimStage::kForwardAuto, plAnimStage::kBackNone, plAnimStage::kAdvanceAuto, plAnimStage::kRegressAuto,
|
|
|
|
0);
|
|
|
|
fLeft = new plAnimStage("WallClimbLeft",
|
|
|
|
plAnimStage::kNotifyEnter, plAnimStage::kForwardAuto, plAnimStage::kBackNone, plAnimStage::kAdvanceAuto, plAnimStage::kRegressAuto,
|
|
|
|
0);
|
|
|
|
fRight = new plAnimStage("WallClimbRight",
|
|
|
|
plAnimStage::kNotifyEnter, plAnimStage::kForwardAuto, plAnimStage::kBackNone, plAnimStage::kAdvanceAuto, plAnimStage::kRegressAuto,
|
|
|
|
0);
|
|
|
|
// the mounts
|
|
|
|
fMountUp = new plAnimStage("WallClimbMountUp",
|
|
|
|
plAnimStage::kNotifyEnter, plAnimStage::kForwardAuto, plAnimStage::kBackNone, plAnimStage::kAdvanceAuto, plAnimStage::kRegressNone,
|
|
|
|
0);
|
|
|
|
fMountDown = new plAnimStage("WallClimbMountDown",
|
|
|
|
plAnimStage::kNotifyEnter, plAnimStage::kForwardAuto, plAnimStage::kBackNone, plAnimStage::kAdvanceAuto, plAnimStage::kRegressNone,
|
|
|
|
0);
|
|
|
|
fMountLeft = new plAnimStage("WallClimbMountLeft",
|
|
|
|
plAnimStage::kNotifyEnter, plAnimStage::kForwardAuto, plAnimStage::kBackNone, plAnimStage::kAdvanceAuto, plAnimStage::kRegressNone,
|
|
|
|
0);
|
|
|
|
fMountRight = new plAnimStage("WallClimbMountRight",
|
|
|
|
plAnimStage::kNotifyEnter, plAnimStage::kForwardAuto, plAnimStage::kBackNone, plAnimStage::kAdvanceAuto, plAnimStage::kRegressNone,
|
|
|
|
0);
|
|
|
|
// and here's the dismount
|
|
|
|
fDismountUp = new plAnimStage("WallClimbDismountUp",
|
|
|
|
plAnimStage::kNotifyEnter, plAnimStage::kForwardAuto, plAnimStage::kBackNone, plAnimStage::kAdvanceAuto, plAnimStage::kRegressNone,
|
|
|
|
0);
|
|
|
|
fDismountDown = new plAnimStage("WallClimbDismountDown",
|
|
|
|
plAnimStage::kNotifyEnter, plAnimStage::kForwardAuto, plAnimStage::kBackNone, plAnimStage::kAdvanceAuto, plAnimStage::kRegressNone,
|
|
|
|
0);
|
|
|
|
fDismountLeft = new plAnimStage("WallClimbDismountLeft",
|
|
|
|
plAnimStage::kNotifyEnter, plAnimStage::kForwardAuto, plAnimStage::kBackNone, plAnimStage::kAdvanceAuto, plAnimStage::kRegressNone,
|
|
|
|
0);
|
|
|
|
fDismountRight = new plAnimStage("WallClimbDismountUp",
|
|
|
|
plAnimStage::kNotifyEnter, plAnimStage::kForwardAuto, plAnimStage::kBackNone, plAnimStage::kAdvanceAuto, plAnimStage::kRegressNone,
|
|
|
|
0);
|
|
|
|
// other
|
|
|
|
fIdle = new plAnimStage("WallClimbIdle",
|
|
|
|
plAnimStage::kNotifyEnter, plAnimStage::kForwardAuto, plAnimStage::kBackNone, plAnimStage::kAdvanceAuto, plAnimStage::kRegressNone,
|
|
|
|
0);
|
|
|
|
fRelease = new plAnimStage("WallClimbRelease",
|
|
|
|
plAnimStage::kNotifyEnter, plAnimStage::kForwardAuto, plAnimStage::kBackNone, plAnimStage::kAdvanceAuto, plAnimStage::kRegressNone,
|
|
|
|
0);
|
|
|
|
fFallOff = new plAnimStage("WallClimbFallOff",
|
|
|
|
plAnimStage::kNotifyEnter, plAnimStage::kForwardAuto, plAnimStage::kBackNone, plAnimStage::kAdvanceAuto, plAnimStage::kRegressNone,
|
|
|
|
0);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// SDL-BASED PERSISTENCE
|
|
|
|
//
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
// SaveToSDL -----------------------------------------
|
|
|
|
// ---------
|
|
|
|
void plAvBrainClimb::SaveToSDL(plStateDataRecord *sdl)
|
|
|
|
{
|
|
|
|
sdl->FindVar(plAvatarSDLModifier::ClimbBrainVarNames::kStrCurMode)->Set(fCurMode);
|
|
|
|
sdl->FindVar(plAvatarSDLModifier::ClimbBrainVarNames::kStrNextMode)->Set(fNextMode);
|
|
|
|
sdl->FindVar(plAvatarSDLModifier::ClimbBrainVarNames::kStrAllowedDirections)->Set((int)fAllowedDirections);
|
|
|
|
sdl->FindVar(plAvatarSDLModifier::ClimbBrainVarNames::kStrAllowedDismounts)->Set((int)fAllowedDismounts);
|
|
|
|
sdl->FindVar(plAvatarSDLModifier::ClimbBrainVarNames::kStrVertProbeLength)->Set(fVerticalProbeLength);
|
|
|
|
sdl->FindVar(plAvatarSDLModifier::ClimbBrainVarNames::kStrHorizProbeLength)->Set(fHorizontalProbeLength);
|
|
|
|
|
|
|
|
bool curStageAttached = fCurStage && fCurStage->GetIsAttached();
|
|
|
|
sdl->FindVar(plAvatarSDLModifier::ClimbBrainVarNames::kStrCurStageAttached)->Set(curStageAttached);
|
|
|
|
if(curStageAttached)
|
|
|
|
{
|
|
|
|
// slightly abuse the "mode" semantics; it happens to work as a persistance format
|
|
|
|
Mode curStageAsMode = IGetModeFromStage(fCurStage);
|
|
|
|
sdl->FindVar(plAvatarSDLModifier::ClimbBrainVarNames::kStrCurStage)->Set(curStageAsMode);
|
|
|
|
|
|
|
|
float curStageTime = fCurStage->GetLocalTime();
|
|
|
|
sdl->FindVar(plAvatarSDLModifier::ClimbBrainVarNames::kStrCurStageTime)->Set(curStageTime);
|
|
|
|
|
|
|
|
float curStageBlend = fCurStage->GetAnimInstance()->GetBlend();
|
|
|
|
sdl->FindVar(plAvatarSDLModifier::ClimbBrainVarNames::kStrCurStageStrength)->Set(curStageBlend);
|
|
|
|
}
|
|
|
|
bool exitStageAttached = fExitStage && fExitStage->GetIsAttached();
|
|
|
|
sdl->FindVar(plAvatarSDLModifier::ClimbBrainVarNames::kStrExitStageAttached)->Set(exitStageAttached);
|
|
|
|
|
|
|
|
if(exitStageAttached)
|
|
|
|
{
|
|
|
|
Mode exitStageAsMode = IGetModeFromStage(fExitStage);
|
|
|
|
sdl->FindVar(plAvatarSDLModifier::ClimbBrainVarNames::kStrExitStage)->Set(exitStageAsMode);
|
|
|
|
|
|
|
|
float exitStageTime = fExitStage->GetLocalTime();
|
|
|
|
sdl->FindVar(plAvatarSDLModifier::ClimbBrainVarNames::kStrExitStageTime)->Set(exitStageTime);
|
|
|
|
|
|
|
|
float exitStageBlend = fExitStage->GetAnimInstance()->GetBlend();
|
|
|
|
sdl->FindVar(plAvatarSDLModifier::ClimbBrainVarNames::kStrExitStageStrength)->Set(exitStageBlend);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// LoadFromSDL -----------------------------------------
|
|
|
|
// -----------
|
|
|
|
void plAvBrainClimb::LoadFromSDL(const plStateDataRecord *sdl)
|
|
|
|
{
|
|
|
|
double curTime = hsTimer::GetSysSeconds();
|
|
|
|
|
|
|
|
sdl->FindVar(plAvatarSDLModifier::ClimbBrainVarNames::kStrCurStage)->Get((int*)&fCurMode);
|
|
|
|
sdl->FindVar(plAvatarSDLModifier::ClimbBrainVarNames::kStrNextMode)->Get((int*)&fNextMode);
|
|
|
|
sdl->FindVar(plAvatarSDLModifier::ClimbBrainVarNames::kStrAllowedDirections)->Get((int*)&fAllowedDirections);
|
|
|
|
sdl->FindVar(plAvatarSDLModifier::ClimbBrainVarNames::kStrAllowedDismounts)->Get((int*)&fAllowedDismounts);
|
|
|
|
sdl->FindVar(plAvatarSDLModifier::ClimbBrainVarNames::kStrVertProbeLength)->Get(&fVerticalProbeLength);
|
|
|
|
sdl->FindVar(plAvatarSDLModifier::ClimbBrainVarNames::kStrHorizProbeLength)->Get(&fHorizontalProbeLength);
|
|
|
|
|
|
|
|
bool curStageAttached = false;
|
|
|
|
sdl->FindVar(plAvatarSDLModifier::ClimbBrainVarNames::kStrCurStageAttached)->Get(&curStageAttached);
|
|
|
|
if(curStageAttached)
|
|
|
|
{
|
|
|
|
Mode *curStageMode; // distinct from curMode; this is just a mode-based representation of the current stage
|
|
|
|
sdl->FindVar(plAvatarSDLModifier::ClimbBrainVarNames::kStrCurStage)->Get((int*)&curStageMode);
|
|
|
|
plAnimStage *curStage = this->IGetStageFromMode(fCurMode);
|
|
|
|
curStage->Attach(fAvMod, this, 0.0f, curTime);
|
|
|
|
|
|
|
|
float curStageTime = 0.0f;
|
|
|
|
sdl->FindVar(plAvatarSDLModifier::ClimbBrainVarNames::kStrCurStageTime)->Get(&curStageTime);
|
|
|
|
curStage->ResetAtTime(curTime, curStageTime, fAvMod); // restart the relative-position sampler
|
|
|
|
|
|
|
|
float curStageBlend = 0.0f;
|
|
|
|
sdl->FindVar(plAvatarSDLModifier::ClimbBrainVarNames::kStrCurStageStrength)->Get(&curStageBlend);
|
|
|
|
curStage->GetAnimInstance()->SetBlend(curStageBlend);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool exitStageAttached;
|
|
|
|
sdl->FindVar(plAvatarSDLModifier::ClimbBrainVarNames::kStrExitStageAttached)->Get(&exitStageAttached);
|
|
|
|
if(exitStageAttached)
|
|
|
|
{
|
|
|
|
Mode exitStageMode; // the exit stage, in mode form
|
|
|
|
sdl->FindVar(plAvatarSDLModifier::ClimbBrainVarNames::kStrExitStage)->Get((int *)&exitStageMode);
|
|
|
|
plAnimStage *exitStage = this->IGetStageFromMode(exitStageMode);
|
|
|
|
sdl->FindVar(plAvatarSDLModifier::ClimbBrainVarNames::kStrExitStageTime)->Get((int *)&fNextMode);
|
|
|
|
sdl->FindVar(plAvatarSDLModifier::ClimbBrainVarNames::kStrExitStageStrength)->Get((int *)&fNextMode);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// READABLE TEXT FOR DEBUGGING
|
|
|
|
//
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
// DumpToDebugDisplay --------------------------------------------------------------------------------------
|
|
|
|
// ------------------
|
|
|
|
void plAvBrainClimb::DumpToDebugDisplay(int &x, int &y, int lineHeight, plDebugText &debugTxt)
|
|
|
|
{
|
|
|
|
debugTxt.DrawString(x, y, "Brain type: Climb");
|
|
|
|
y += lineHeight;
|
|
|
|
const char * worldDir = WorldDirStr(fDesiredDirection);
|
|
|
|
const char * modeStr = ModeStr(fCurMode);
|
|
|
|
|
|
|
|
char buffy[256];
|
|
|
|
sprintf(buffy, "direction: %s mode: %s controlDir: %f", worldDir, modeStr, fControlDir);
|
|
|
|
debugTxt.DrawString(x,y, buffy);
|
|
|
|
y += lineHeight;
|
|
|
|
|
|
|
|
IDumpClimbDirections(x, y, lineHeight, debugTxt);
|
|
|
|
IDumpDismountDirections(x, y, lineHeight, debugTxt);
|
|
|
|
IDumpBlockedDirections(x, y, lineHeight, debugTxt);
|
|
|
|
|
|
|
|
fUp->DumpDebug(fUp == fCurStage, x, y, lineHeight, debugTxt);
|
|
|
|
fDown->DumpDebug(fDown == fCurStage, x, y, lineHeight, debugTxt);
|
|
|
|
fLeft->DumpDebug(fLeft == fCurStage, x, y, lineHeight, debugTxt);
|
|
|
|
fRight->DumpDebug(fRight == fCurStage, x, y, lineHeight, debugTxt);
|
|
|
|
fMountUp->DumpDebug(fMountUp == fCurStage, x, y, lineHeight, debugTxt);
|
|
|
|
fMountDown->DumpDebug(fMountDown == fCurStage, x, y, lineHeight, debugTxt);
|
|
|
|
fMountLeft->DumpDebug(fMountLeft == fCurStage, x, y, lineHeight, debugTxt);
|
|
|
|
fMountRight->DumpDebug(fMountRight == fCurStage, x, y, lineHeight, debugTxt);
|
|
|
|
fDismountUp->DumpDebug(fDismountUp == fCurStage, x, y, lineHeight, debugTxt);
|
|
|
|
fDismountDown->DumpDebug(fDismountDown == fCurStage, x, y, lineHeight, debugTxt);
|
|
|
|
fDismountLeft->DumpDebug(fDismountLeft == fCurStage, x, y, lineHeight, debugTxt);
|
|
|
|
fDismountRight->DumpDebug(fDismountRight == fCurStage, x, y, lineHeight, debugTxt);
|
|
|
|
fIdle->DumpDebug(fIdle == fCurStage, x, y, lineHeight, debugTxt);
|
|
|
|
fRelease->DumpDebug(fRelease == fCurStage, x, y, lineHeight, debugTxt);
|
|
|
|
fFallOff->DumpDebug(fFallOff == fCurStage, x, y, lineHeight, debugTxt);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// IDumpClimbDirections --------------------------------------------------------------------------------------
|
|
|
|
// --------------------
|
|
|
|
void plAvBrainClimb::IDumpClimbDirections(int &x, int &y, int lineHeight, plDebugText &debugTxt)
|
|
|
|
{
|
|
|
|
static const char prolog[] = "Allowed directions: ";
|
|
|
|
plStringStream str;
|
|
|
|
|
|
|
|
str << prolog;
|
|
|
|
if(fAllowedDirections & plClimbMsg::kUp)
|
|
|
|
str << "UP ";
|
|
|
|
if(fAllowedDirections & plClimbMsg::kDown)
|
|
|
|
str << "DOWN ";
|
|
|
|
if(fAllowedDirections & plClimbMsg::kLeft)
|
|
|
|
str << "LEFT ";
|
|
|
|
if(fAllowedDirections & plClimbMsg::kRight)
|
|
|
|
str << "RIGHT ";
|
|
|
|
|
|
|
|
if(str.GetLength() == strlen(prolog))
|
|
|
|
str << "- NONE -";
|
|
|
|
|
|
|
|
debugTxt.DrawString(x, y, str.GetString());
|
|
|
|
y += lineHeight;
|
|
|
|
}
|
|
|
|
|
|
|
|
// IDumpDismountDirections --------------------------------------------------------------------------------------
|
|
|
|
// -----------------------
|
|
|
|
void plAvBrainClimb::IDumpDismountDirections(int &x, int &y, int lineHeight, plDebugText &debugTxt)
|
|
|
|
{
|
|
|
|
static const char prolog[] = "Enabled dismounts: ";
|
|
|
|
plStringStream str;
|
|
|
|
|
|
|
|
str << prolog;
|
|
|
|
if(fAllowedDismounts & plClimbMsg::kUp)
|
|
|
|
str << "UP ";
|
|
|
|
if(fAllowedDismounts & plClimbMsg::kDown)
|
|
|
|
str << "DOWN ";
|
|
|
|
if(fAllowedDismounts & plClimbMsg::kLeft)
|
|
|
|
str << "LEFT ";
|
|
|
|
if(fAllowedDismounts & plClimbMsg::kRight)
|
|
|
|
str << "RIGHT ";
|
|
|
|
|
|
|
|
if(str.GetLength() == strlen(prolog))
|
|
|
|
str << "- NONE -";
|
|
|
|
|
|
|
|
debugTxt.DrawString(x, y, str.GetString());
|
|
|
|
y += lineHeight;
|
|
|
|
}
|
|
|
|
|
|
|
|
void plAvBrainClimb::IDumpBlockedDirections(int &x, int &y, int lineHeight, plDebugText &debugTxt)
|
|
|
|
{
|
|
|
|
static const char prolog[] = "Physically blocked: ";
|
|
|
|
plStringStream str;
|
|
|
|
|
|
|
|
str << prolog;
|
|
|
|
if(fOldPhysicallyBlockedDirections & plClimbMsg::kUp)
|
|
|
|
str << "UP ";
|
|
|
|
if(fOldPhysicallyBlockedDirections & plClimbMsg::kDown)
|
|
|
|
str << "DOWN ";
|
|
|
|
if(fOldPhysicallyBlockedDirections & plClimbMsg::kLeft)
|
|
|
|
str << "LEFT ";
|
|
|
|
if(fOldPhysicallyBlockedDirections & plClimbMsg::kRight)
|
|
|
|
str << "RIGHT ";
|
|
|
|
|
|
|
|
if(str.GetLength() == strlen(prolog))
|
|
|
|
str << "- NONE -";
|
|
|
|
|
|
|
|
debugTxt.DrawString(x, y, str.GetString());
|
|
|
|
y += lineHeight;
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *plAvBrainClimb::WorldDirStr(plClimbMsg::Direction dir)
|
|
|
|
{
|
|
|
|
switch(dir)
|
|
|
|
{
|
|
|
|
case plClimbMsg::kUp:
|
|
|
|
return "Up";
|
|
|
|
case plClimbMsg::kDown:
|
|
|
|
return "Down";
|
|
|
|
case plClimbMsg::kLeft:
|
|
|
|
return "Left";
|
|
|
|
case plClimbMsg::kRight:
|
|
|
|
return "Right";
|
|
|
|
case plClimbMsg::kCenter:
|
|
|
|
return "Center";
|
|
|
|
default:
|
|
|
|
return "WTF?";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *plAvBrainClimb::ModeStr(Mode mode)
|
|
|
|
{
|
|
|
|
switch(mode)
|
|
|
|
{
|
|
|
|
case kInactive:
|
|
|
|
return "Inactive";
|
|
|
|
case kUnknown:
|
|
|
|
return "Unknown";
|
|
|
|
case kFinishing:
|
|
|
|
return "Finishing";
|
|
|
|
case kDone:
|
|
|
|
return "Done";
|
|
|
|
case kClimbingUp:
|
|
|
|
return "ClimbingUp";
|
|
|
|
case kClimbingDown:
|
|
|
|
return "ClimbingDown";
|
|
|
|
case kClimbingLeft:
|
|
|
|
return "ClimbingLeft";
|
|
|
|
case kClimbingRight:
|
|
|
|
return "ClimbingRight";
|
|
|
|
case kMountingUp:
|
|
|
|
return "MountingUp";
|
|
|
|
case kMountingDown:
|
|
|
|
return "MountingDown";
|
|
|
|
case kMountingLeft:
|
|
|
|
return "MountingLeft";
|
|
|
|
case kMountingRight:
|
|
|
|
return "MountingRight";
|
|
|
|
case kDismountingUp:
|
|
|
|
return "MountingUp";
|
|
|
|
case kDismountingDown:
|
|
|
|
return "DismountingDown";
|
|
|
|
case kDismountingLeft:
|
|
|
|
return "DismountingLeft";
|
|
|
|
case kDismountingRight:
|
|
|
|
return "DismountingRight";
|
|
|
|
case kIdle:
|
|
|
|
return "Idle";
|
|
|
|
case kReleasing:
|
|
|
|
return "Releasing";
|
|
|
|
case kFallingOff:
|
|
|
|
return "FallingOff";
|
|
|
|
default:
|
|
|
|
return "WTF?!";
|
|
|
|
}
|
|
|
|
}
|