/*==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 . 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 "plAvCallbackAction.h" // havok-contaminated file: must go first // singular #include "plAvBrainGeneric.h" // local #include "plAnimStage.h" #include "plArmatureMod.h" // #include "plAvatarTasks.h" #include "plAvTask.h" #include "plAvTaskBrain.h" #include "plAvBrainHuman.h" #include "plAGAnimInstance.h" #include "plMatrixChannel.h" // global #include "hsTimer.h" #include "plgDispatch.h" // other #include "pnNetCommon/plSDLTypes.h" #include "pnMessage/plCameraMsg.h" #include "pnMessage/plNotifyMsg.h" #include "plMessage/plAvatarMsg.h" #include "plMessage/plInputEventMsg.h" #include "plMessage/plSimStateMsg.h" #include "plMessage/plConsoleMsg.h" #include "plPipeline/plDebugText.h" #include "plInputCore/plAvatarInputInterface.h" #include "plMessage/plInputIfaceMgrMsg.h" #ifdef DEBUG_MULTISTAGE #include "plAvatarMgr.h" #include "plStatusLog/plStatusLog.h" #endif hsBool plAvBrainGeneric::fForce3rdPerson = true; const hsScalar plAvBrainGeneric::kDefaultFadeIn = 6.f; // 1/6th of a second to fade in const hsScalar plAvBrainGeneric::kDefaultFadeOut = 0.f; // instant fade out. // plAvBrainGeneric ---------------- // ----------------- plAvBrainGeneric::plAvBrainGeneric() : fRecipient(nil), fStages(TRACKED_NEW plAnimStageVec), fCurStage(0), fType(kGeneric), fExitFlags(kExitNormal), fMode(kEntering), fForward(true), fStartMessage(nil), fEndMessage(nil), fFadeIn(0.0f), fFadeOut(0.0f), fMoveMode(kMoveRelative), fCallbackAction(nil), fBodyUsage(plAGAnim::kBodyUnknown) { } // plAvBrainGeneric -------------------------------------- // ----------------- plAvBrainGeneric::plAvBrainGeneric(plAnimStageVec *stages, plMessage *startMessage, plMessage *endMessage, plKey recipient, UInt32 exitFlags, float fadeIn, float fadeOut, MoveMode moveMode) : plArmatureBrain(), fRecipient(recipient), fStages(stages), fCurStage(0), fType(kGeneric), fExitFlags(exitFlags), fMode(kEntering), fForward(true), fStartMessage(startMessage), fEndMessage(endMessage), fFadeIn(fadeIn), fFadeOut(fadeOut), fMoveMode(moveMode), fCallbackAction(nil), fBodyUsage(plAGAnim::kBodyUnknown) { } // plAvBrainGeneric plAvBrainGeneric::plAvBrainGeneric(UInt32 exitFlags, float fadeIn, float fadeOut, MoveMode moveMode) : fRecipient(nil), fStages(nil), fCurStage(0), fType(kGeneric), fExitFlags(exitFlags), fMode(kEntering), fForward(true), fStartMessage(nil), fEndMessage(nil), fFadeIn(fadeIn), fFadeOut(fadeOut), fMoveMode(moveMode), fCallbackAction(nil), fBodyUsage(plAGAnim::kBodyUnknown) { } // ~plAvBrainGeneric ---------------- // ------------------ plAvBrainGeneric::~plAvBrainGeneric() { int fNumStages = fStages->size(); for(int i = 0; i < fNumStages; i++) { plAnimStage *stage = (*fStages)[i]; (*fStages)[i] = nil; stage->Detach(fAvMod); delete stage; } delete fStages; } // Activate ------------------------------------------- // --------- void plAvBrainGeneric::Activate(plArmatureModBase *avMod) { plArmatureBrain::Activate(avMod); if ((GetType() == kEmote || GetType() == kAFK || GetType() == kSitOnGround) && fAvMod->IsLocalAvatar()) { plInputIfaceMgrMsg* msg = TRACKED_NEW plInputIfaceMgrMsg(plInputIfaceMgrMsg::kDisableClickables ); plgDispatch::MsgSend(msg); } int numStages = fStages->size(); if (!numStages) return; plAnimStage *stage = (*fStages)[fCurStage]; bool useFadeIn = fFadeIn > 0.0f; float initialBlend = useFadeIn ? 0.0f : 1.0f; if (GetType() == kEmote) ((plArmatureMod*)avMod)->SendBehaviorNotify(plHBehavior::kBehaviorTypeEmote,true); double worldTime = hsTimer::GetSysSeconds(); if (fMoveMode == kMoveRelative || fMoveMode == kMoveAbsolute) { // enable kinematic... ignore outside forces... but still collide with detector regions fAvMod->EnablePhysicsKinematic( true ); } else if(fMoveMode == kMoveStandstill) { // Avatar stands still automatically now, so we do nothing here } if (stage->Attach(fAvMod, this, initialBlend, worldTime)) { if(fStartMessage) { fStartMessage->Send(); fStartMessage = nil; } if (plAvBrainGeneric::fForce3rdPerson && fAvMod->IsLocalAvatar()) { // create message to force 3rd person mode plCameraMsg* pMsg = TRACKED_NEW plCameraMsg; pMsg->SetBCastFlag(plMessage::kBCastByExactType); pMsg->SetCmd(plCameraMsg::kResponderSetThirdPerson); pMsg->SetBCastFlag(plMessage::kNetPropagate, false); plgDispatch::MsgSend( pMsg ); // whoosh... off it goes } } if (fType == kLadder && fAvMod->IsLocalAvatar()) plAvatarInputInterface::GetInstance()->SetLadderMode(); if (fReverseFBControlsOnRelease) fAvMod->SetReverseFBOnIdle(true); } hsBool plAvBrainGeneric::IsRunningTask() { if ( fStages->size() > 0 ) return true; return false; } bool plAvBrainGeneric::MatchAnimNames(const char *names[], int count) { if (count != GetStageCount()) return false; int i; for (i = 0; i < count; i++) { if (strcmp(names[i], GetStage(i)->GetAnimName())) return false; // different names. } return true; } // Apply ---------------------------------------------------- // ------ hsBool plAvBrainGeneric::Apply(double time, hsScalar elapsed) { hsBool result = false; switch(fMode) { case kAbort: break; case kEntering: case kFadingIn: result = IProcessFadeIn(time, elapsed); break; case kExit: case kFadingOut: // go through the fade logic whether or not we actually need a fade; // centralizes some exit conditions. result = IProcessFadeOut(time, elapsed); break; case kNormal: result = IProcessNormal(time, elapsed); break; } plArmatureBrain::Apply(time, elapsed); return result; } // Deactivate ----------------------- // ----------- void plAvBrainGeneric::Deactivate() { if (fEndMessage) { fEndMessage->Send(); fEndMessage = nil; } if (fMode != kAbort) // we're being forcibly removed... IExitMoveMode(); if (fMoveMode == kMoveRelative || fMoveMode == kMoveAbsolute) { // re-enable normal physics... outside forces affect us fAvMod->EnablePhysicsKinematic( false ); } else if (fMoveMode == kMoveStandstill) { // Avatar stands still automaticaly now, so we do nothing here } if (fType == plAvBrainGeneric::kLadder && fAvMod->IsLocalAvatar()) { plAvatarInputInterface::GetInstance()->ClearLadderMode(); } if (fReverseFBControlsOnRelease) fAvMod->SetReverseFBOnIdle(false); if (plAvBrainGeneric::fForce3rdPerson && fAvMod->IsLocalAvatar()) { // create message to force 3rd person mode 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 } plArmatureBrain::Deactivate(); if ((GetType() == kEmote || GetType() == kAFK || GetType() == kSitOnGround) && fAvMod->IsLocalAvatar()) { plInputIfaceMgrMsg* msg = TRACKED_NEW plInputIfaceMgrMsg(plInputIfaceMgrMsg::kEnableClickables ); plgDispatch::MsgSend(msg); } } // GETRECIPIENT plKey plAvBrainGeneric::GetRecipient() { return fRecipient; } // SETRECIPIENT void plAvBrainGeneric::SetRecipient(const plKey &recipient) { fRecipient = recipient; } // RELAYNOTIFYMSG bool plAvBrainGeneric::RelayNotifyMsg(plNotifyMsg *msg) { if(fRecipient) { msg->AddReceiver(fRecipient); msg->Send(); return true; } else { return false; } } // IGetAnimDelta ------------------------------------------------ // -------------- float plAvBrainGeneric::IGetAnimDelta(double time, float elapsed) { float delta = 0.0f; plAnimStage *curStage = (*fStages)[fCurStage]; plAnimStage::ForwardType forward = curStage->GetForwardType(); plAnimStage::BackType back = curStage->GetBackType(); bool fwdIsDown = (fReverseFBControlsOnRelease && fAvMod->IsFBReversed()) ? fAvMod->BackwardKeyDown() : fAvMod->ForwardKeyDown(); hsBool backIsDown = (fReverseFBControlsOnRelease && fAvMod->IsFBReversed()) ? fAvMod->ForwardKeyDown() : fAvMod->BackwardKeyDown(); // forward with a key down gets top priority if(forward == plAnimStage::kForwardKey && fwdIsDown) { // key drive forward, forward key is down delta = elapsed; fForward = true; } else if(back == plAnimStage::kBackKey && backIsDown) { // key drive back, back key is down delta = -elapsed; fForward = false; } else if (forward == plAnimStage::kForwardAuto && fForward) { // auto drive forward delta = elapsed; } else if (back == plAnimStage::kBackAuto && ! fForward) { // auto drive backward delta = -elapsed; } return delta; } // IProcessNormal ------------------------------------------------- // --------------- hsBool plAvBrainGeneric::IProcessNormal(double time, float elapsed) { plAnimStage *curStage = (*fStages)[fCurStage]; if(curStage) { float animDelta = IGetAnimDelta(time, elapsed); // how far to move the anim (may be negative) float overage; hsBool done = curStage->MoveRelative(time, animDelta, overage, fAvMod); if(done) { bool forward = animDelta > 0.0f; int nextStage = forward ? curStage->GetNextStage(fCurStage) : curStage->GetPrevStage(fCurStage); if((nextStage == -1) || (nextStage >= fStages->size())) { // ran off one end; we're done. fMode = kExit; } else { ISwitchStages(fCurStage, nextStage, overage, false, 0.0f, 1.0f, -1.0f, time); } } return true; } else { // current stage is missing; abort return false; } } // IProcessFadeIn ------------------------------------------------- // --------------- hsBool plAvBrainGeneric::IProcessFadeIn(double time, float elapsed) { plAnimStage *curStage = (*fStages)[fCurStage]; if(fMode != kFadingIn) { bool needFade = fFadeIn != 0.0f; if(fFadeIn == 0.0f) { IEnterMoveMode(time); // if fadeIn's not zero, we have to wait until fade's done // before animating } else { plAGAnimInstance *curAnim = curStage->GetAnimInstance(); if(curAnim) curAnim->Fade(1.0f, fFadeIn); } fMode = kFadingIn; } else { plAGAnimInstance *curAnim = curStage->GetAnimInstance(); float curBlend = 1.0f; if(curAnim) curBlend = curAnim->GetBlend(); if(curBlend == 1.0f) { IEnterMoveMode(time); } } return true; } // IProcessFadeOut ------------------------------------------------- // ---------------- hsBool plAvBrainGeneric::IProcessFadeOut(double time, float elapsed) { plAnimStage *curStage = (*fStages)[fCurStage]; if(fMode != kFadingOut) { // haven't actually started fading; see if we need to if(fFadeOut > 0.0f) { plAGAnimInstance *curAnim = curStage->GetAnimInstance(); if(curAnim) { curAnim->Fade(0.0f, fFadeOut); IExitMoveMode(); fMode = kFadingOut; } else { fMode = kAbort; return false; } } else { curStage->Detach(fAvMod); IExitMoveMode(); fMode = kAbort; } } else { // already fading; just keeping looking for the anim to zero out. plAGAnimInstance *curAnim = curStage->GetAnimInstance(); float curBlend = 0.0f; if(curAnim) curBlend = curAnim->GetBlend(); if(curBlend == 0.0f) { curStage->Detach(fAvMod); fMode = kAbort; } } return true; } // ISwitchStages --------------------------------------------------------------------------------------------------- // -------------- hsBool plAvBrainGeneric::ISwitchStages(int oldStageNum, int newStageNum, float delta, hsBool setTime, float newTime, float fadeNew, hsScalar fadeOld, double worldTime) { #ifdef DEBUG_MULTISTAGE char sbuf[256]; sprintf(sbuf,"ISwitchStage - old=%d new=%d (fCurStage=%d)",oldStageNum,newStageNum,fCurStage); plAvatarMgr::GetInstance()->GetLog()->AddLine(sbuf); #endif if(oldStageNum != newStageNum) { plAnimStage *newStage = fStages->at(newStageNum); plAnimStage *oldStage = fStages->at(oldStageNum); if(setTime) newStage->SetLocalTime(newTime); hsAssert(oldStageNum < fStages->size(), "PLAVBRAINGENERIC: Stage out of range."); oldStage->Detach(fAvMod); newStage->Attach(fAvMod, this, 1.0f, worldTime); fCurStage = newStageNum; fAvMod->DirtySynchState(kSDLAvatar, 0); // write our new stage to the server } if(setTime) { plAnimStage *curStage = fStages->at(fCurStage); curStage->SetLocalTime(newTime); } if(fMoveMode == kMoveRelative) fAvMod->GetRootAnimator()->Reset(worldTime); return true; } void plAvBrainGeneric::IEnterMoveMode(double time) { if(fMoveMode == kMoveRelative) { fAvMod->GetRootAnimator()->Enable(true); fAvMod->GetRootAnimator()->Reset(time); } fMode = kNormal; } void plAvBrainGeneric::IExitMoveMode() { if(fAvMod) { if(fMoveMode == kMoveRelative) { if(fAvMod->GetRootAnimator()) fAvMod->GetRootAnimator()->Enable(false); } if (fFadeOut == 0.f) { // if we're exiting instantly (no fade out) then the end of the animation expects to line up with // the first frame of the idle animation, so we need to reset it. plAvBrainHuman *brain = plAvBrainHuman::ConvertNoRef(fAvMod->FindBrainByClass(plAvBrainHuman::Index())); if (brain) brain->ResetIdle(); } } } ///////////////////////////////////////////////////////////////////////////////////////// // // MESSAGE HANDLING // ///////////////////////////////////////////////////////////////////////////////////////// // MsgReceive ------------------------------------- // ----------- hsBool plAvBrainGeneric::MsgReceive(plMessage *msg) { hsBool result = false; plAvBrainGenericMsg *genMsg = plAvBrainGenericMsg::ConvertNoRef(msg); //plAvExitModeMsg *exitMsg = plAvExitModeMsg::ConvertNoRef(msg); plAvTaskMsg *taskMsg = plAvTaskMsg::ConvertNoRef(msg); plControlEventMsg *ctrlMsg = plControlEventMsg::ConvertNoRef(msg); if(genMsg) { result = IHandleGenBrainMsg(genMsg); } // else if(exitMsg) { // fMode = kExit; // result = true; // } else if (taskMsg) { result = IHandleTaskMsg(taskMsg); } else if (ctrlMsg && (fExitFlags & kExitAnyInput) ) { fMode = kExit; } if(result == false) // if still haven't handled msg { if(fMode == kExit) // if we're exiting { result = fAvMod->GetNextBrain(this)->MsgReceive(msg); // pass msg to next brain } else { // otherwise result = plArmatureBrain::MsgReceive(msg); // pass msg to base class } } return result; } // IHandleGenBrainMsg ----------------------------------------------------- // ------------------- hsBool plAvBrainGeneric::IHandleGenBrainMsg(const plAvBrainGenericMsg *msg) { hsBool setTime = msg->fSetTime; float newTime = msg->fNewTime; hsBool setDirection = msg->fSetDirection; bool newDirection = msg->fNewDirection ? true : false; double worldTime = hsTimer::GetSysSeconds(); switch(msg->fType) { case plAvBrainGenericMsg::kGotoStage: { int wantStage = msg->fWhichStage; #ifdef DEBUG_MULTISTAGE char sbuf[256]; sprintf(sbuf,"GenericMsg - Goto Stage %d (oldstage %d)",wantStage,fCurStage); plAvatarMgr::GetInstance()->GetLog()->AddLine(sbuf); #endif if(wantStage == -1) { fMode = kExit; } else { int count = fStages->size(); if(wantStage < count && wantStage >= 0) { ISwitchStages(fCurStage, wantStage, 0.0f, setTime, newTime, 1.0f, -1.0f, worldTime); // direction is set within the brain, not the stage if(setDirection) fForward = newDirection; } } } break; case plAvBrainGenericMsg::kNextStage: { int wantStage = fCurStage + 1; #ifdef DEBUG_MULTISTAGE char sbuf[256]; sprintf(sbuf,"GenericMsg - Next Stage %d (oldstage %d)",wantStage,fCurStage); plAvatarMgr::GetInstance()->GetLog()->AddLine(sbuf); #endif if(wantStage == fStages->size()) { fMode = kExit; // walked off the end of the brain } else { ISwitchStages(fCurStage, wantStage, 0.0f, setTime, newTime, 1.0f, -1.0f, worldTime); if(setDirection) fForward = newDirection; } } break; case plAvBrainGenericMsg::kPrevStage: { int wantStage = fCurStage - 1; #ifdef DEBUG_MULTISTAGE char sbuf[256]; sprintf(sbuf,"GenericMsg - PrevStage %d (oldstage %d)",wantStage,fCurStage); plAvatarMgr::GetInstance()->GetLog()->AddLine(sbuf); #endif if(wantStage < 0) { fMode = kExit; // walked off the beginning of the brain } else { ISwitchStages(fCurStage, wantStage, 0.0f, setTime, 0.0f, 1.0f, -1.0f, worldTime); if(setDirection) fForward = newDirection; } } break; #ifdef DEBUG_MULTISTAGE default: { char sbuf[256]; sprintf(sbuf,"GenericMsg - Unknown command %d ",msg->fType); plAvatarMgr::GetInstance()->GetLog()->AddLine(sbuf); } break; #endif } return true; } hsBool plAvBrainGeneric::IHandleTaskMsg(plAvTaskMsg *msg) { plAvTask *task = msg->GetTask(); plAvTaskBrain *brainTask = plAvTaskBrain::ConvertNoRef(task); if(brainTask) { plArmatureBrain * brain = brainTask->GetBrain(); if(brain) { if(fExitFlags & kExitNewBrain) { // RULE 1: if kExitNewBrain, exit on any new brain fMode = kExit; return false; // we didn't consume the message } else { plAvBrainGeneric * gBrain = plAvBrainGeneric::ConvertNoRef(brain); if(gBrain && IBrainIsCompatible(gBrain)) { // RULE 2: if not kExitNewBrain and brain is compatible, apply it QueueTask(brainTask); return true; } else { if(fMode == kExit || fMode == kFadingOut) { // RULE 3: if brain is incompatible and we're exiting anyway, // queue it to be next fAvMod->GetNextBrain(this)->QueueTask(brainTask); return true; } // RULE 4: if brain is incompatible and we're still running, ignore. } } } else { // no brain; it's an exit task, exit and CONSUME it. fMode = kExit; return true; } } else { // note that this check has to come after the brain task check; if it's a brain // task we need to examine it so we can say whether we consumed it or not. // popbrain messages get consumed, even if we exit on any task. if(fExitFlags & kExitAnyTask) { // RULE 4: if kExitAnyTask, exit on any task (but if it was an exit brain task, // make sure to consume it ) fMode = kExit; return false; } } // RULE 4: if brain is incompatible and we're still running, ignore. return false; } bool plAvBrainGeneric::IBrainIsCompatible(plAvBrainGeneric *otherBrain) { plAGAnim::BodyUsage otherUsage = otherBrain->GetBodyUsage(); switch(fBodyUsage) { case plAGAnim::kBodyUnknown: return false; break; case plAGAnim::kBodyFull: return false; break; case plAGAnim::kBodyUpper: if(otherUsage == plAGAnim::kBodyLower) return true; else return false; break; case plAGAnim::kBodyLower: if(otherUsage == plAGAnim::kBodyUpper) return true; else return false; break; } return false; } ///////////////////////////////////////////////////////////////////////////////////////// // // READ/WRITE // ///////////////////////////////////////////////////////////////////////////////////////// // Write ---------------------------------------------------- // ------ void plAvBrainGeneric::Write(hsStream *stream, hsResMgr *mgr) { plArmatureBrain::Write(stream, mgr); int numStages = fStages->size(); stream->WriteSwap32(numStages); for(int i = 0; i < numStages; i++) { plAnimStage *stage = (*fStages)[i]; plCreatable *cre = reinterpret_cast(stage); mgr->WriteCreatable(stream, cre); // save base state // ** replace this with Write(..) stage->SaveAux(stream, mgr); // save ephemeral state } stream->WriteSwap32(fCurStage); stream->WriteSwap32(fType); stream->WriteSwap32(fExitFlags); stream->WriteByte(fMode); stream->Writebool(fForward); if(fStartMessage) { stream->WriteBool(true); mgr->WriteCreatable(stream, fStartMessage); } else { stream->WriteBool(false); } if(fEndMessage) { stream->WriteBool(true); mgr->WriteCreatable(stream, fEndMessage); } else { stream->WriteBool(false); } stream->WriteSwapScalar(fFadeIn); stream->WriteSwapScalar(fFadeOut); stream->WriteByte(fMoveMode); stream->WriteByte(fBodyUsage); mgr->WriteKey(stream, fRecipient); } // Read ---------------------------------------------------- // ----- void plAvBrainGeneric::Read(hsStream *stream, hsResMgr *mgr) { plArmatureBrain::Read(stream, mgr); int numStages = stream->ReadSwap32(); for(int i = 0; i < numStages; i++) { plCreatable *created = mgr->ReadCreatable(stream); // load base state plAnimStage *stage = reinterpret_cast(created); // Replace this with Read(..) stage->LoadAux(stream, mgr, 0.0); // load ephemeral state fStages->push_back(stage); } fCurStage = stream->ReadSwap32(); fType = static_cast(stream->ReadSwap32()); fExitFlags = stream->ReadSwap32(); fMode = static_cast(stream->ReadByte()); fForward = stream->Readbool(); if(stream->ReadBool()) { fStartMessage = plMessage::ConvertNoRef(mgr->ReadCreatable(stream)); } else { fStartMessage = nil; } if(stream->ReadBool()) { fEndMessage = plMessage::ConvertNoRef(mgr->ReadCreatable(stream)); } else { fEndMessage = nil; } fFadeIn = stream->ReadSwapScalar(); fFadeOut = stream->ReadSwapScalar(); fMoveMode = static_cast(stream->ReadByte()); fBodyUsage = static_cast(stream->ReadByte()); fRecipient = mgr->ReadKey(stream); } ///////////////////////////////////////////////////////////////////////////////////////// // // MINOR FNs / GETTERS & SETTERS // ///////////////////////////////////////////////////////////////////////////////////////// // LeaveAge --------------------- // --------- hsBool plAvBrainGeneric::LeaveAge() { IExitMoveMode(); fMode = kAbort; return true; } // AddStage -------------------------------------- // --------- int plAvBrainGeneric::AddStage(plAnimStage *stage) { if(!fStages) fStages = TRACKED_NEW plAnimStageVec; fStages->push_back(stage); return fStages->size() - 1; } // GetStageNum -------------------------------------- // ------------ int plAvBrainGeneric::GetStageNum(plAnimStage *stage) { int count = fStages->size(); for(int i = 0; i < count; i++) { plAnimStage *any = (*fStages)[i]; if(any == stage) { return i; } } return -1; } // GetCurStageNum -------------------- // --------------- int plAvBrainGeneric::GetCurStageNum() { return fCurStage; } // GetStageCount -------------------- // -------------- int plAvBrainGeneric::GetStageCount() { return fStages->size(); } // GetStage --------------------------------------- // --------- plAnimStage * plAvBrainGeneric::GetStage(int which) { return fStages->at(which); } // GetCurStage ------------------------------ // ------------ plAnimStage * plAvBrainGeneric::GetCurStage() { return fStages->at(fCurStage); } // SetType ------------------------------------------------------------------------------- // -------- plAvBrainGeneric::BrainType plAvBrainGeneric::SetType(plAvBrainGeneric::BrainType newType) { BrainType oldType = fType; fType = newType; return oldType; } // GetType -------------------------------------------- // -------- plAvBrainGeneric::BrainType plAvBrainGeneric::GetType() { return fType; } plAGAnim::BodyUsage plAvBrainGeneric::GetBodyUsage() { return fBodyUsage; } void plAvBrainGeneric::SetBodyUsage(plAGAnim::BodyUsage bodyUsage) { fBodyUsage = bodyUsage; } ///////////////////////////////////////////////////////////////////////////////////////// // // DEBUGGING // ///////////////////////////////////////////////////////////////////////////////////////// // DumpToDebugDisplay ---------------------------------------------------------------------------------------- // ------------------- void plAvBrainGeneric::DumpToDebugDisplay(int &x, int &y, int lineHeight, char *strBuf, plDebugText &debugTxt) { debugTxt.DrawString(x, y, "Brain type: Generic AKA Multistage"); y += lineHeight; int stageCount = fStages->size(); for(int i = 0; i < stageCount; i++) { plAnimStage *stage = (*fStages)[i]; stage->DumpDebug(i == fCurStage, x, y, lineHeight, strBuf, debugTxt); } }