diff --git a/MOULOpenSourceClientPlugin/Plasma20/MSVC10Projects/Plasma/PubUtilLib/plAvatar/plAvatar.vcxproj b/MOULOpenSourceClientPlugin/Plasma20/MSVC10Projects/Plasma/PubUtilLib/plAvatar/plAvatar.vcxproj index 4f719944..bdff6ddc 100644 --- a/MOULOpenSourceClientPlugin/Plasma20/MSVC10Projects/Plasma/PubUtilLib/plAvatar/plAvatar.vcxproj +++ b/MOULOpenSourceClientPlugin/Plasma20/MSVC10Projects/Plasma/PubUtilLib/plAvatar/plAvatar.vcxproj @@ -328,7 +328,6 @@ %(PreprocessorDefinitions) %(PreprocessorDefinitions) - Disabled Disabled @@ -555,7 +554,6 @@ %(PreprocessorDefinitions) %(PreprocessorDefinitions) - Disabled Disabled @@ -807,7 +805,6 @@ - @@ -825,7 +822,6 @@ - diff --git a/MOULOpenSourceClientPlugin/Plasma20/MSVC10Projects/Plasma/PubUtilLib/plAvatar/plAvatar.vcxproj.filters b/MOULOpenSourceClientPlugin/Plasma20/MSVC10Projects/Plasma/PubUtilLib/plAvatar/plAvatar.vcxproj.filters index 4f4cb2d2..a1d89d7d 100644 --- a/MOULOpenSourceClientPlugin/Plasma20/MSVC10Projects/Plasma/PubUtilLib/plAvatar/plAvatar.vcxproj.filters +++ b/MOULOpenSourceClientPlugin/Plasma20/MSVC10Projects/Plasma/PubUtilLib/plAvatar/plAvatar.vcxproj.filters @@ -35,9 +35,6 @@ Source Files - - Source Files - Source Files @@ -86,9 +83,6 @@ Source Files - - Source Files - Source Files @@ -163,9 +157,6 @@ Header Files - - Header Files - Header Files @@ -217,9 +208,6 @@ Header Files - - Header Files - Header Files diff --git a/MOULOpenSourceClientPlugin/Plasma20/MsDevProjects/Plasma/PubUtilLib/plAvatar/plAvatar.vcproj b/MOULOpenSourceClientPlugin/Plasma20/MsDevProjects/Plasma/PubUtilLib/plAvatar/plAvatar.vcproj index ae798721..f8d53b38 100644 --- a/MOULOpenSourceClientPlugin/Plasma20/MsDevProjects/Plasma/PubUtilLib/plAvatar/plAvatar.vcproj +++ b/MOULOpenSourceClientPlugin/Plasma20/MsDevProjects/Plasma/PubUtilLib/plAvatar/plAvatar.vcproj @@ -282,26 +282,6 @@ PreprocessorDefinitions=""/> - - - - - - - - - - - - - - - - - - @@ -993,9 +950,6 @@ - - diff --git a/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/FeatureLib/pfAudio/plListener.cpp b/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/FeatureLib/pfAudio/plListener.cpp index 3dd47931..48401135 100644 --- a/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/FeatureLib/pfAudio/plListener.cpp +++ b/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/FeatureLib/pfAudio/plListener.cpp @@ -57,7 +57,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com #include "../plAvatar/plAvatarMgr.h" #include "../plAvatar/plArmatureMod.h" -#include "../plAvatar/plAvCallbackAction.h" +#include "../plAvatar/plPhysicalControllerCore.h" hsBool plListener::fPrintDbgInfo = false; diff --git a/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/FeatureLib/pfCamera/plCameraModifier.cpp b/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/FeatureLib/pfCamera/plCameraModifier.cpp index 0a40eb29..90397012 100644 --- a/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/FeatureLib/pfCamera/plCameraModifier.cpp +++ b/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/FeatureLib/pfCamera/plCameraModifier.cpp @@ -63,7 +63,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com #include "../pnSceneObject/plSimulationInterface.h" #include "../plAvatar/plAvatarMgr.h" #include "../plAvatar/plArmatureMod.h" -#include "../plAvatar/plAvCallbackAction.h" +#include "../plAvatar/plPhysicalControllerCore.h" // new stuff diff --git a/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/FeatureLib/pfPython/pySceneObject.cpp b/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/FeatureLib/pfPython/pySceneObject.cpp index c7bacef2..20e8dcc2 100644 --- a/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/FeatureLib/pfPython/pySceneObject.cpp +++ b/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/FeatureLib/pfPython/pySceneObject.cpp @@ -545,7 +545,7 @@ hsBool pySceneObject::IsAvatar() return false; } -#include "../plAvatar/plAvCallbackAction.h" +#include "../plAvatar/plPhysicalControllerCore.h" PyObject* pySceneObject::GetAvatarVelocity() { diff --git a/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAnimStage.cpp b/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAnimStage.cpp index 917ff1e0..129c052e 100644 --- a/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAnimStage.cpp +++ b/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAnimStage.cpp @@ -39,7 +39,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com Mead, WA 99021 *==LICENSE==*/ -#include "plAvCallbackAction.h" // must be first: references havok new // singular #include "plAnimStage.h" diff --git a/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAntiGravAction.cpp b/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAntiGravAction.cpp deleted file mode 100644 index e78d319e..00000000 --- a/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAntiGravAction.cpp +++ /dev/null @@ -1,171 +0,0 @@ -/*==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 . - -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==*/ -#if 0 -// havok first -#include -#include - -#include "plAntiGravAction.h" - -#include "../pnSceneObject/plSceneObject.h" -#include "../plHavok1/plHKPhysical.h" -#include "../plAvatar/plSwimRegion.h" -#include "hsTimer.h" - -// This is meant to be a specific physicsAction for the swim behavior -plAntiGravAction::plAntiGravAction(plHKPhysical *physical, plAGApplicator *rootApp) : - plAnimatedCallbackAction(physical, rootApp), - fOnGround(false), - fBuoyancy(1.f), - fSurfaceHeight(0.f), - fCurrentRegion(nil), - fHadContacts(false) -{ -} - -plSimDefs::ActionType plAntiGravAction::GetType() -{ - return plSimDefs::kAntiGravAction; -} - -void plAntiGravAction::apply(Havok::Subspace &space, Havok::hkTime time) -{ - double elapsed = time.asDouble() - getRefresh().asDouble(); - setRefresh(time); - - IAdjustBuoyancy(); - Havok::RigidBody *body = fPhysical->GetBody(); - float mass = body->getMass(); - Havok::Vector3 gravity = space.getGravity(); - Havok::Vector3 force = -gravity * (mass * fBuoyancy); - body->applyForce(force); - - hsVector3 vel; - fPhysical->GetLinearVelocitySim(vel); - fAnimPosVel.fZ = vel.fZ; - - hsVector3 linCurrent(0.f, 0.f, 0.f); - hsScalar angCurrent = 0.f; - if (fCurrentRegion != nil) - fCurrentRegion->GetCurrent(fPhysical, linCurrent, angCurrent, (hsScalar)elapsed); - - int numContacts = fPhysical->GetNumContacts(); - fHadContacts = (numContacts > 0); - - const Havok::Vector3 straightUp(0.0f, 0.0f, 1.0f); - fOnGround = false; - int i; - for (i = 0; i < numContacts; i++) - { - const Havok::ContactPoint *contact = fPhysical->GetContactPoint(i); - hsScalar dotUp = straightUp.dot(contact->m_normal); - if (dotUp > .5) - { - fOnGround = true; - break; - } - } - - fPhysical->SetLinearVelocitySim(fAnimPosVel + linCurrent); - fPhysical->SetAngularVelocitySim(hsVector3(0.f, 0.f, fAnimAngVel + fTurnStr + angCurrent)); -} - -void plAntiGravAction::SetSurface(plSwimRegionInterface *region, hsScalar surfaceHeight) -{ - fCurrentRegion = region; - if (region != nil) - fSurfaceHeight = surfaceHeight; -} - -void plAntiGravAction::IAdjustBuoyancy() -{ - // "surface depth" refers to the depth our handle object should be below - // the surface for the avatar to be "at the surface" - static const float surfaceDepth = 4.0f; - // 1.0 = neutral buoyancy - // 0 = no buoyancy (normal gravity) - // 2.0 = opposite of gravity, floating upwards - static const float buoyancyAtSurface = 1.0f; - - if (fCurrentRegion == nil) - { - fBuoyancy = 0.f; - return; - } - - hsMatrix44 l2w, w2l; - fPhysical->GetTransform(l2w, w2l); - float depth = fSurfaceHeight - surfaceDepth - l2w.GetTranslate().fZ; - if (depth < -1) - fBuoyancy = 0.f; // Same as being above ground. Plain old gravity. - else if (depth < 0) - fBuoyancy = 1 + depth; - else - { - hsVector3 vel; - fPhysical->GetLinearVelocitySim(vel); - if (vel.fZ > 0) - { - if (vel.fZ > fCurrentRegion->fMaxUpwardVel) - { - vel.fZ = fCurrentRegion->fMaxUpwardVel; - fPhysical->SetLinearVelocitySim(vel); - } - else - { - if (depth > 1) - fBuoyancy = fCurrentRegion->fUpBuoyancy; - else - fBuoyancy = (fCurrentRegion->fUpBuoyancy - 1) * depth + 1; - } - } - else - { - if (depth > 1) - fBuoyancy = fCurrentRegion->fDownBuoyancy; - else - fBuoyancy = (fCurrentRegion->fDownBuoyancy - 1) * depth + 1; - } - } -} - -#endif \ No newline at end of file diff --git a/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAntiGravAction.h b/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAntiGravAction.h deleted file mode 100644 index f8dd2125..00000000 --- a/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAntiGravAction.h +++ /dev/null @@ -1,79 +0,0 @@ -/*==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 . - -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==*/ -#if 0//ndef PL_ANTI_GRAV_ACTION_H -#define PL_ANTI_GRAV_ACTION_H - -#include "plAvCallbackAction.h" - -class plSwimRegionInterface; - -class plAntiGravAction : public plAnimatedCallbackAction -{ -public: - plAntiGravAction(plHKPhysical *physical, plAGApplicator *rootApp); - - /** Return the type of the action as defined in the enum plSimDefs::ActionType. - Used to retrieve actions by entity/type indexing, and to - reuse actions that can be shared between entities. */ - virtual plSimDefs::ActionType GetType(); - - /** Called by Havok at substep frequency. */ - void apply(Havok::Subspace &s, Havok::hkTime time); - - void SetSurface(plSwimRegionInterface *region, hsScalar surfaceHeight); - hsScalar GetBuoyancy() { return fBuoyancy; } - hsBool IsOnGround() { return fOnGround; } - hsBool HadContacts() { return fHadContacts; } - -protected: - void IAdjustBuoyancy(); - - hsBool fOnGround; - hsBool fHadContacts; - hsScalar fBuoyancy; - hsScalar fSurfaceHeight; - plSwimRegionInterface *fCurrentRegion; -}; - -#endif - - diff --git a/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plArmatureEffects.cpp b/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plArmatureEffects.cpp index 2f6907f6..16835813 100644 --- a/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plArmatureEffects.cpp +++ b/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plArmatureEffects.cpp @@ -39,7 +39,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com Mead, WA 99021 *==LICENSE==*/ -#include "plAvCallbackAction.h" #include "../plStatusLog/plStatusLog.h" #include "plArmatureEffects.h" diff --git a/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plArmatureMod.cpp b/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plArmatureMod.cpp index 8f879739..051219c7 100644 --- a/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plArmatureMod.cpp +++ b/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plArmatureMod.cpp @@ -54,7 +54,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com #include "plAvBrainHuman.h" #include "plMatrixChannel.h" #include "plAvatarTasks.h" -#include "plAvCallbackAction.h" +#include "plPhysicalControllerCore.h" #include "plAvBrainCritter.h" // global @@ -534,8 +534,7 @@ void plArmatureModBase::EnablePhysics(hsBool status, UInt16 reason /* = kDisable // i.e. normal enabled physical void plArmatureModBase::EnablePhysicsKinematic(hsBool status) { - if (fController) - fController->Kinematic(status); + EnablePhysics(!status, kDisableReasonKinematic); } void plArmatureModBase::EnableDrawing(hsBool status, UInt16 reason /* = kDisableReasonUnknown */) @@ -2684,19 +2683,7 @@ void plArmatureMod::DumpToDebugDisplay(int &x, int &y, int lineHeight, char *str debugTxt.DrawString(x, y, strBuf); y += lineHeight; - hsPoint3 kPos; - char *kinematic = "n.a."; const char* frozen = "n.a."; - if (fController) - { - fController->GetKinematicPosition(kPos); - kinematic = fController->IsKinematic() ? "on" : "off"; - } - sprintf(strBuf, "kinematc(world): %.2f, %.2f, %.2f Kinematic: %3s", - kPos.fX, kPos.fY, kPos.fZ,kinematic); - debugTxt.DrawString(x, y, strBuf); - y += lineHeight; - if (fController) frozen = fController->IsEnabled() ? "no" : "yes"; diff --git a/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plArmatureMod.h b/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plArmatureMod.h index afc1cddf..8353125e 100644 --- a/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plArmatureMod.h +++ b/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plArmatureMod.h @@ -145,6 +145,7 @@ public: kDisableReasonCCR = 0x0008, kDisableReasonVehicle = 0x0010, kDisableReasonGenericBrain = 0x0020, + kDisableReasonKinematic = 0x0040 }; void EnablePhysics(hsBool status, UInt16 reason = kDisableReasonUnknown); void EnablePhysicsKinematic(hsBool status); diff --git a/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvBrainCritter.cpp b/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvBrainCritter.cpp index 7a6ad23f..b86912cf 100644 --- a/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvBrainCritter.cpp +++ b/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvBrainCritter.cpp @@ -42,7 +42,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com #include "hsConfig.h" #include "hsWindows.h" -#include "plAvCallbackAction.h" +#include "plPhysicalControllerCore.h" #include "plAvBrainCritter.h" #include "plAvBrainHuman.h" #include "plArmatureMod.h" @@ -127,7 +127,7 @@ protected: /////////////////////////////////////////////////////////////////////////////// -plAvBrainCritter::plAvBrainCritter(): fCallbackAction(nil), fCurMode(kIdle), fNextMode(kIdle), fFadingNextBehavior(true), +plAvBrainCritter::plAvBrainCritter(): fWalkingStrategy(nil), fCurMode(kIdle), fNextMode(kIdle), fFadingNextBehavior(true), fLocallyControlled(false), fAvoidingAvatars(false), fFinalGoalPos(0, 0, 0), fImmediateGoalPos(0, 0, 0), fDotGoal(0), fAngRight(0) { @@ -145,8 +145,8 @@ plAvBrainCritter::~plAvBrainCritter() fBehaviors[i] = nil; } - delete fCallbackAction; - fCallbackAction = nil; + delete fWalkingStrategy; + fWalkingStrategy = nil; fUserBehaviors.clear(); fReceivers.clear(); @@ -169,8 +169,8 @@ hsBool plAvBrainCritter::Apply(double time, hsScalar elapsed) IProcessBehavior(time, elapsed); // just continue with the currently running one // update our controller to keep us turned and moving to where we want to go - fCallbackAction->RecalcVelocity(time, time - elapsed); - fCallbackAction->SetTurnStrength(IGetTurnStrength(time)); + fWalkingStrategy->SetTurnStrength(IGetTurnStrength(time)); + fWalkingStrategy->RecalcVelocity(time, elapsed); return plArmatureBrain::Apply(time, elapsed); } @@ -190,13 +190,13 @@ void plAvBrainCritter::Activate(plArmatureModBase* avMod) IInitBaseAnimations(); // create the controller if we haven't done so already - if (!fCallbackAction) + if (!fWalkingStrategy) { plSceneObject* avObj = fArmature->GetTarget(0); plAGModifier* agMod = const_cast(plAGModifier::ConvertNoRef(FindModifierByClass(avObj, plAGModifier::Index()))); plPhysicalControllerCore* controller = avMod->GetController(); - fCallbackAction = TRACKED_NEW plWalkingController(avObj, agMod->GetApplicator(kAGPinTransform), controller); - fCallbackAction->ActivateController(); + fWalkingStrategy = TRACKED_NEW plWalkingStrategy(agMod->GetApplicator(kAGPinTransform), controller); + controller->SetMovementStrategy(fWalkingStrategy); } // tell people that care that we are good to go @@ -226,7 +226,7 @@ void plAvBrainCritter::Resume() // fade in the idle fNextMode = kIdle; - fCallbackAction->Reset(false); + fWalkingStrategy->Reset(false); plArmatureBrain::Resume(); } diff --git a/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvBrainCritter.h b/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvBrainCritter.h index ab44245b..7b6359d7 100644 --- a/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvBrainCritter.h +++ b/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvBrainCritter.h @@ -47,7 +47,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com #include "../pnKeyedObject/plKey.h" class plArmatureMod; -class plWalkingController; +class plWalkingStrategy; class plAIMsg; class plAvBrainCritter : public plArmatureBrain @@ -127,8 +127,6 @@ public: virtual void DumpToDebugDisplay(int& x, int& y, int lineHeight, char* strBuf, plDebugText& debugTxt); - plWalkingController* GetCallbackAction() {return fCallbackAction;} - // For the console static bool fDrawDebug; @@ -152,7 +150,7 @@ protected: std::vector IAvatarsICanSee() const; std::vector IAvatarsICanHear() const; - plWalkingController* fCallbackAction; + plWalkingStrategy* fWalkingStrategy; int fCurMode; // current behavior we are running int fNextMode; // the next behavior to run (-1 if we aren't switching on next eval) bool fFadingNextBehavior; // is the next behavior supposed to blend? diff --git a/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvBrainDrive.cpp b/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvBrainDrive.cpp index 9521cf95..1a5b6cb5 100644 --- a/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvBrainDrive.cpp +++ b/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvBrainDrive.cpp @@ -42,7 +42,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com // local includes #include "plAvBrainDrive.h" #include "plArmatureMod.h" -#include "plAvCallbackAction.h" // global includes #include "hsTimer.h" diff --git a/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvBrainGeneric.cpp b/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvBrainGeneric.cpp index d20862b9..32655893 100644 --- a/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvBrainGeneric.cpp +++ b/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvBrainGeneric.cpp @@ -39,7 +39,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com Mead, WA 99021 *==LICENSE==*/ -#include "plAvCallbackAction.h" // havok-contaminated file: must go first // singular #include "plAvBrainGeneric.h" @@ -94,7 +93,6 @@ plAvBrainGeneric::plAvBrainGeneric() fFadeIn(0.0f), fFadeOut(0.0f), fMoveMode(kMoveRelative), - fCallbackAction(nil), fBodyUsage(plAGAnim::kBodyUnknown) { } @@ -122,7 +120,6 @@ plAvBrainGeneric::plAvBrainGeneric(plAnimStageVec *stages, fFadeIn(fadeIn), fFadeOut(fadeOut), fMoveMode(moveMode), - fCallbackAction(nil), fBodyUsage(plAGAnim::kBodyUnknown) { } @@ -141,7 +138,6 @@ plAvBrainGeneric::plAvBrainGeneric(UInt32 exitFlags, float fadeIn, float fadeOut fFadeIn(fadeIn), fFadeOut(fadeOut), fMoveMode(moveMode), - fCallbackAction(nil), fBodyUsage(plAGAnim::kBodyUnknown) { diff --git a/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvBrainGeneric.h b/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvBrainGeneric.h index 79be24fc..fc3c16c2 100644 --- a/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvBrainGeneric.h +++ b/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvBrainGeneric.h @@ -49,7 +49,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com class plAnimStage; class plAnimStageVec; class plAvBrainGenericMsg; -class plHorizontalFreezeAction; class plNotifyMsg; /** \class plAvBrainGeneric @@ -300,7 +299,6 @@ protected: int fCurStage; // which stage are we playing? (zero-based) BrainType fType; // what type of brain are we? UInt32 fExitFlags; // what will cause us to exit? - plHorizontalFreezeAction *fCallbackAction; bool fForward; // are we currently moving forward or backward through the stages? // this is used by the "auto-" movement types in the stages diff --git a/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvBrainHuman.cpp b/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvBrainHuman.cpp index b6acd180..62ac40e5 100644 --- a/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvBrainHuman.cpp +++ b/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvBrainHuman.cpp @@ -42,9 +42,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com #include "hsConfig.h" #include "hsWindows.h" -#include "plAvCallbackAction.h" // subclasses a havok object; must be in first include section - - +#include "plPhysicalControllerCore.h" #include "plAvBrainHuman.h" #include "plAvBrainClimb.h" #include "plAvBrainDrive.h" @@ -142,7 +140,7 @@ plAvBrainHuman::TurnCurve plAvBrainHuman::GetTurnCurve(hsBool walk) plAvBrainHuman::plAvBrainHuman(bool isActor /* = false */) : fHandleAGMod(nil), fStartedTurning(-1.0f), - fCallbackAction(nil), + fWalkingStrategy(nil), fPreconditions(0), fIsActor(isActor) { @@ -156,9 +154,9 @@ hsBool plAvBrainHuman::Apply(double timeNow, hsScalar elapsed) #endif // SetTurnStrength runs first to make sure it's set to a sane value // (or cleared). RunStandardBehaviors may overwrite it. - fCallbackAction->SetTurnStrength(IGetTurnStrength(timeNow)); + fWalkingStrategy->SetTurnStrength(IGetTurnStrength(timeNow)); RunStandardBehaviors(timeNow, elapsed); - fCallbackAction->RecalcVelocity(timeNow, timeNow - elapsed, (fPreconditions & plHBehavior::kBehaviorTypeNeedsRecalcMask)); + fWalkingStrategy->RecalcVelocity(timeNow, elapsed, (fPreconditions & plHBehavior::kBehaviorTypeNeedsRecalcMask)); plArmatureBrain::Apply(timeNow, elapsed); #ifndef _DEBUG @@ -179,13 +177,13 @@ void plAvBrainHuman::Activate(plArmatureModBase *avMod) IInitBoneMap(); IInitAnimations(); - if (!fCallbackAction) + if (!fWalkingStrategy) { plSceneObject* avObj = fArmature->GetTarget(0); plAGModifier* agMod = const_cast(plAGModifier::ConvertNoRef(FindModifierByClass(avObj, plAGModifier::Index()))); plPhysicalControllerCore* controller = avMod->GetController(); - fCallbackAction = TRACKED_NEW plWalkingController(avObj, agMod->GetApplicator(kAGPinTransform), controller); - fCallbackAction->ActivateController(); + fWalkingStrategy = TRACKED_NEW plWalkingStrategy(agMod->GetApplicator(kAGPinTransform), controller); + controller->SetMovementStrategy(fWalkingStrategy); } @@ -330,8 +328,8 @@ plAvBrainHuman::~plAvBrainHuman() delete fBehaviors[i]; fBehaviors.Reset(); - delete fCallbackAction; - fCallbackAction = nil; + delete fWalkingStrategy; + fWalkingStrategy = nil; } void plAvBrainHuman::Deactivate() @@ -364,7 +362,7 @@ void plAvBrainHuman::Resume() if (fAvMod->GetInputFlag(S_PUSH_TO_TALK)) IChatOn(); - fCallbackAction->Reset(false); + fWalkingStrategy->Reset(false); plArmatureBrain::Resume(); } @@ -468,25 +466,23 @@ hsBool plAvBrainHuman::MsgReceive(plMessage * msg) { if(ride->Entering()) { - //plAvBrainRideAnimatedPhysical *rideBrain = TRACKED_NEW plAvBrainRideAnimatedPhysical(); - //fAvMod->PushBrain(rideBrain); - delete fCallbackAction; + // Switch to dynamic walking strategy + delete fWalkingStrategy; plSceneObject* avObj = fArmature->GetTarget(0); plAGModifier* agMod = const_cast(plAGModifier::ConvertNoRef(FindModifierByClass(avObj, plAGModifier::Index()))); plPhysicalControllerCore* controller = fAvMod->GetController(); - fCallbackAction= TRACKED_NEW plRidingAnimatedPhysicalController(avObj, agMod->GetApplicator(kAGPinTransform), controller); - fCallbackAction->ActivateController(); - + fWalkingStrategy = TRACKED_NEW plDynamicWalkingStrategy(agMod->GetApplicator(kAGPinTransform), controller); + controller->SetMovementStrategy(fWalkingStrategy); } else { - delete fCallbackAction; + // Restore default walking strategy + delete fWalkingStrategy; plSceneObject* avObj = fArmature->GetTarget(0); plAGModifier* agMod = const_cast(plAGModifier::ConvertNoRef(FindModifierByClass(avObj, plAGModifier::Index()))); plPhysicalControllerCore* controller = fAvMod->GetController(); - fCallbackAction= TRACKED_NEW plWalkingController(avObj, agMod->GetApplicator(kAGPinTransform), controller); - fCallbackAction->ActivateController(); - //hsStatusMessage("Got an exiting ride animated physical message"); + fWalkingStrategy = TRACKED_NEW plWalkingStrategy(agMod->GetApplicator(kAGPinTransform), controller); + controller->SetMovementStrategy(fWalkingStrategy); } } @@ -560,8 +556,8 @@ hsScalar plAvBrainHuman::IGetTurnStrength(double timeNow) // Turning based on keypress if ((turnLeftStrength > 0.f) || (turnRightStrength > 0.f) - || (!fCallbackAction->IsOnGround() - && !fCallbackAction->IsControlledFlight()) + || (!fWalkingStrategy->IsOnGround() + && !fWalkingStrategy->IsControlledFlight()) ) { float t = (float)(timeNow - fStartedTurning); float turnSpeed; @@ -593,7 +589,7 @@ hsScalar plAvBrainHuman::IGetTurnStrength(double timeNow) result += fAvMod->GetKeyTurnStrength() * turnSpeed; } - if (!fCallbackAction->IsControlledFlight()) + if (!fWalkingStrategy->IsControlledFlight()) result += fAvMod->GetAnalogTurnStrength() * maxTurnSpeed; return result; @@ -650,7 +646,7 @@ void plAvBrainHuman::ResetIdle() void plAvBrainHuman::IdleOnly(bool instantOff) { - if (!fCallbackAction) + if (!fWalkingStrategy) return; hsScalar rate = instantOff ? 0.f : 1.f; @@ -676,7 +672,7 @@ bool plAvBrainHuman::IsMovementZeroBlend() void plAvBrainHuman::TurnToPoint(hsPoint3 point) { - if (!fCallbackAction->IsOnGround() || IsRunningTask() || fAvMod->GetCurrentBrain() != this || !IsMovementZeroBlend()) + if (!fWalkingStrategy->IsOnGround() || IsRunningTask() || fAvMod->GetCurrentBrain() != this || !IsMovementZeroBlend()) return; hsPoint3 avPos; @@ -875,23 +871,23 @@ void plAvBrainHuman::Spawn(double timeNow) hsBool plAvBrainHuman::LeaveAge() { plPhysicalControllerCore* controller = fAvMod->GetController(); - if(!controller->BehavingLikeAnAnimatedPhysical()) + + // If our current walking strategy is dynamic, restore the default kinematic strategy. + if (!fWalkingStrategy->IsKinematic()) { - controller->BehaveLikeAnimatedPhysical(true); - delete fCallbackAction; + delete fWalkingStrategy; plSceneObject* avObj = fArmature->GetTarget(0); plAGModifier* agMod = const_cast(plAGModifier::ConvertNoRef(FindModifierByClass(avObj, plAGModifier::Index()))); - fCallbackAction= TRACKED_NEW plWalkingController(avObj, agMod->GetApplicator(kAGPinTransform), controller); - fCallbackAction->ActivateController(); + fWalkingStrategy = TRACKED_NEW plWalkingStrategy(agMod->GetApplicator(kAGPinTransform), controller); } - plArmatureBrain::LeaveAge(); - + fWalkingStrategy->Reset(true); + + plArmatureBrain::LeaveAge(); // pin the physical so it doesn't fall when the world is deleted fAvMod->EnablePhysics(false); - // this will get set to true when we hit ground - fCallbackAction->Reset(true); + return false; } @@ -901,11 +897,10 @@ void plAvBrainHuman::DumpToDebugDisplay(int &x, int &y, int lineHeight, char *st debugTxt.DrawString(x, y, strBuf); y += lineHeight; - const char *grounded = fCallbackAction->IsOnGround() ? "yes" : "no"; - const char *falseGrounded = fCallbackAction->IsOnFalseGround() ? "yes" : "no"; - const char *pushing = (fCallbackAction->GetPushingPhysical() ? (fCallbackAction->GetFacingPushingPhysical() ? "facing" : "behind") : "none"); - sprintf(strBuf, "Ground: %3s, FalseGround: %3s, AirTime: %5.2f (Peak: %5.2f), PushingPhys: %6s", - grounded, falseGrounded, fCallbackAction->GetAirTime(), fCallbackAction->GetImpactTime(), pushing); + const char *grounded = fWalkingStrategy->IsOnGround() ? "yes" : "no"; + const char *pushing = (fWalkingStrategy->GetPushingPhysical() ? (fWalkingStrategy->GetFacingPushingPhysical() ? "facing" : "behind") : "none"); + sprintf(strBuf, "Ground: %3s, AirTime: %5.2f (Peak: %5.2f), PushingPhys: %6s", + grounded, fWalkingStrategy->GetAirTime(), fWalkingStrategy->GetImpactTime(), pushing); debugTxt.DrawString(x, y, strBuf); y += lineHeight; @@ -1018,8 +1013,8 @@ hsBool Run::PreCondition(double time, float elapsed) { if (fAnim) { - if (fAvMod->ForwardKeyDown() && fAvMod->FastKeyDown() && fHuBrain->fCallbackAction->IsOnGround() && - (!fHuBrain->fCallbackAction->GetPushingPhysical() || !fHuBrain->fCallbackAction->GetFacingPushingPhysical())) + if (fAvMod->ForwardKeyDown() && fAvMod->FastKeyDown() && fHuBrain->fWalkingStrategy->IsOnGround() && + (!fHuBrain->fWalkingStrategy->GetPushingPhysical() || !fHuBrain->fWalkingStrategy->GetFacingPushingPhysical())) return true; } return false; @@ -1029,8 +1024,8 @@ hsBool Walk::PreCondition(double time, float elapsed) { if (fAnim) { - if (fAvMod->ForwardKeyDown() && !fAvMod->FastKeyDown() && fHuBrain->fCallbackAction->IsOnGround() && - (!fHuBrain->fCallbackAction->GetPushingPhysical() || !fHuBrain->fCallbackAction->GetFacingPushingPhysical())) + if (fAvMod->ForwardKeyDown() && !fAvMod->FastKeyDown() && fHuBrain->fWalkingStrategy->IsOnGround() && + (!fHuBrain->fWalkingStrategy->GetPushingPhysical() || !fHuBrain->fWalkingStrategy->GetFacingPushingPhysical())) return true; } return false; @@ -1040,8 +1035,8 @@ hsBool WalkBack::PreCondition(double time, float elapsed) { if (fAnim) { - if (fAvMod->BackwardKeyDown() && !fAvMod->ForwardKeyDown() && fHuBrain->fCallbackAction->IsOnGround() && - (!fHuBrain->fCallbackAction->GetPushingPhysical() || fHuBrain->fCallbackAction->GetFacingPushingPhysical())) + if (fAvMod->BackwardKeyDown() && !fAvMod->ForwardKeyDown() && fHuBrain->fWalkingStrategy->IsOnGround() && + (!fHuBrain->fWalkingStrategy->GetPushingPhysical() || fHuBrain->fWalkingStrategy->GetFacingPushingPhysical())) return true; } return false; @@ -1054,7 +1049,7 @@ hsBool StepLeft::PreCondition(double time, float elapsed) return ((fAvMod->StrafeLeftKeyDown() || (fAvMod->StrafeKeyDown() && fAvMod->TurnLeftKeyDown())) && !(fAvMod->StrafeRightKeyDown() || (fAvMod->StrafeKeyDown() && fAvMod->TurnRightKeyDown())) && !(fAvMod->ForwardKeyDown() || fAvMod->BackwardKeyDown()) && - fHuBrain->fCallbackAction->IsOnGround()); + fHuBrain->fWalkingStrategy->IsOnGround()); } return false; } @@ -1066,7 +1061,7 @@ hsBool StepRight::PreCondition(double time, float elapsed) return ((fAvMod->StrafeRightKeyDown() || (fAvMod->StrafeKeyDown() && fAvMod->TurnRightKeyDown())) && !(fAvMod->StrafeLeftKeyDown() || (fAvMod->StrafeKeyDown() && fAvMod->TurnLeftKeyDown())) && !(fAvMod->ForwardKeyDown() || fAvMod->BackwardKeyDown()) && - fHuBrain->fCallbackAction->IsOnGround()); + fHuBrain->fWalkingStrategy->IsOnGround()); } return false; } @@ -1107,8 +1102,8 @@ hsBool MovingTurnLeft::PreCondition(double time, float elapsed) { if (fAvMod->GetTurnStrength() > 0) { - if (fHuBrain->fCallbackAction->IsOnGround() && (fAvMod->ForwardKeyDown() || fAvMod->BackwardKeyDown()) && - (!fHuBrain->fCallbackAction->GetPushingPhysical() || !fHuBrain->fCallbackAction->GetFacingPushingPhysical())) + if (fHuBrain->fWalkingStrategy->IsOnGround() && (fAvMod->ForwardKeyDown() || fAvMod->BackwardKeyDown()) && + (!fHuBrain->fWalkingStrategy->GetPushingPhysical() || !fHuBrain->fWalkingStrategy->GetFacingPushingPhysical())) return true; } return false; @@ -1118,8 +1113,8 @@ hsBool MovingTurnRight::PreCondition(double time, float elapsed) { if (fAvMod->GetTurnStrength() < 0) { - if (fHuBrain->fCallbackAction->IsOnGround() && (fAvMod->ForwardKeyDown() || fAvMod->BackwardKeyDown()) && - (!fHuBrain->fCallbackAction->GetPushingPhysical() || !fHuBrain->fCallbackAction->GetFacingPushingPhysical())) + if (fHuBrain->fWalkingStrategy->IsOnGround() && (fAvMod->ForwardKeyDown() || fAvMod->BackwardKeyDown()) && + (!fHuBrain->fWalkingStrategy->GetPushingPhysical() || !fHuBrain->fWalkingStrategy->GetFacingPushingPhysical())) return true; } @@ -1128,14 +1123,14 @@ hsBool MovingTurnRight::PreCondition(double time, float elapsed) void Jump::IStart() { - fHuBrain->fCallbackAction->EnableControlledFlight(true); + fHuBrain->fWalkingStrategy->EnableControlledFlight(true); plHBehavior::IStart(); } void Jump::IStop() { - fHuBrain->fCallbackAction->EnableControlledFlight(false); + fHuBrain->fWalkingStrategy->EnableControlledFlight(false); plHBehavior::IStop(); } @@ -1146,7 +1141,7 @@ hsBool StandingJump::PreCondition(double time, float elapsed) { if (GetStrength() > 0.f) { - if (!fHuBrain->fCallbackAction->IsControlledFlight() || + if (!fHuBrain->fWalkingStrategy->IsControlledFlight() || fAnim->GetTimeConvert()->WorldToAnimTimeNoUpdate(time) >= fAnim->GetTimeConvert()->GetEnd()) { return false; @@ -1158,7 +1153,7 @@ hsBool StandingJump::PreCondition(double time, float elapsed) if (fAvMod->JumpKeyDown() && !fAvMod->ForwardKeyDown() && fAnim->GetBlend() == 0.0f && - fHuBrain->fCallbackAction->IsOnGround()) + fHuBrain->fWalkingStrategy->IsOnGround()) { if (fAvMod->ConsumeJump()) return true; @@ -1174,7 +1169,7 @@ hsBool WalkingJump::PreCondition(double time, float elapsed) { if (GetStrength() > 0.f) { - if (!fHuBrain->fCallbackAction->IsControlledFlight() || + if (!fHuBrain->fWalkingStrategy->IsControlledFlight() || fAnim->GetTimeConvert()->WorldToAnimTimeNoUpdate(time) >= fAnim->GetTimeConvert()->GetEnd()) { return false; @@ -1187,8 +1182,8 @@ hsBool WalkingJump::PreCondition(double time, float elapsed) !fAvMod->FastKeyDown() && fAvMod->ForwardKeyDown() && fAnim->GetBlend() == 0.0f && - fHuBrain->fCallbackAction->IsOnGround() && - (!fHuBrain->fCallbackAction->GetPushingPhysical() || !fHuBrain->fCallbackAction->GetFacingPushingPhysical())) + fHuBrain->fWalkingStrategy->IsOnGround() && + (!fHuBrain->fWalkingStrategy->GetPushingPhysical() || !fHuBrain->fWalkingStrategy->GetFacingPushingPhysical())) { if (fAvMod->ConsumeJump()) return true; @@ -1204,7 +1199,7 @@ hsBool RunningJump::PreCondition(double time, float elapsed) { if (GetStrength() > 0.f) { - if (!fHuBrain->fCallbackAction->IsControlledFlight() || + if (!fHuBrain->fWalkingStrategy->IsControlledFlight() || fAnim->GetTimeConvert()->WorldToAnimTimeNoUpdate(time) >= fAnim->GetTimeConvert()->GetEnd()) { return false; @@ -1217,8 +1212,8 @@ hsBool RunningJump::PreCondition(double time, float elapsed) fAvMod->ForwardKeyDown() && fAvMod->FastKeyDown() && fAnim->GetBlend() == 0.0f && - fHuBrain->fCallbackAction->IsOnGround() && - (!fHuBrain->fCallbackAction->GetPushingPhysical() || !fHuBrain->fCallbackAction->GetFacingPushingPhysical())) + fHuBrain->fWalkingStrategy->IsOnGround() && + (!fHuBrain->fWalkingStrategy->GetPushingPhysical() || !fHuBrain->fWalkingStrategy->GetFacingPushingPhysical())) { if (fAvMod->ConsumeJump()) return true; @@ -1243,13 +1238,13 @@ hsBool RunningImpact::PreCondition(double time, float elapsed) { if (fDuration > 0.0f) fDuration = fDuration - elapsed; - else if (fHuBrain->fCallbackAction->IsOnGround() && fHuBrain->fCallbackAction->GetImpactTime() > kMinAirTime) + else if (fHuBrain->fWalkingStrategy->IsOnGround() && fHuBrain->fWalkingStrategy->GetImpactTime() > kMinAirTime) { - if (fHuBrain->fCallbackAction->GetImpactVelocity().fZ < -kMinImpactVel) + if (fHuBrain->fWalkingStrategy->GetImpactVelocity().fZ < -kMinImpactVel) { - if (fHuBrain->fCallbackAction->GetImpactVelocity().fY < kRunningImpactThresh) + if (fHuBrain->fWalkingStrategy->GetImpactVelocity().fY < kRunningImpactThresh) { - fMaxBlend = 0.5f + (0.5f * (-fHuBrain->fCallbackAction->GetImpactVelocity().fZ / (kFullImpactVel - kMinImpactVel))); + fMaxBlend = 0.5f + (0.5f * (-fHuBrain->fWalkingStrategy->GetImpactVelocity().fZ / (kFullImpactVel - kMinImpactVel))); if (fMaxBlend > 1) fMaxBlend = 1; fDuration = 1.0f / fFadeIn; @@ -1273,13 +1268,13 @@ hsBool GroundImpact::PreCondition(double time, float elapsed) bool result = false; if (fDuration > 0.0f) fDuration = fDuration - elapsed; - else if (fHuBrain->fCallbackAction->IsOnGround() && fHuBrain->fCallbackAction->GetImpactTime() > kMinAirTime) + else if (fHuBrain->fWalkingStrategy->IsOnGround() && fHuBrain->fWalkingStrategy->GetImpactTime() > kMinAirTime) { - if (fHuBrain->fCallbackAction->GetImpactVelocity().fZ < -kMinImpactVel) + if (fHuBrain->fWalkingStrategy->GetImpactVelocity().fZ < -kMinImpactVel) { - if (fHuBrain->fCallbackAction->GetImpactVelocity().fY >= kRunningImpactThresh) + if (fHuBrain->fWalkingStrategy->GetImpactVelocity().fY >= kRunningImpactThresh) { - fMaxBlend = 0.5f + (0.5f * (-fHuBrain->fCallbackAction->GetImpactVelocity().fZ / (kFullImpactVel - kMinImpactVel))); + fMaxBlend = 0.5f + (0.5f * (-fHuBrain->fWalkingStrategy->GetImpactVelocity().fZ / (kFullImpactVel - kMinImpactVel))); if (fMaxBlend > 1) fMaxBlend = 1; fDuration = 1.0f / fFadeIn; @@ -1298,7 +1293,7 @@ void GroundImpact::IStop() hsBool Fall::PreCondition(double time, float elapsed) { - return !fHuBrain->fCallbackAction->IsOnGround() && fHuBrain->fCallbackAction->HitGroundInThisAge(); + return !fHuBrain->fWalkingStrategy->IsOnGround() && fHuBrain->fWalkingStrategy->HitGroundInThisAge(); } void Fall::Process(double time, float elapsed) @@ -1310,7 +1305,7 @@ void Fall::Process(double time, float elapsed) if (fAnim && fAnim->GetBlend() > 0.8) { float panicThresh = plAvBrainHuman::kAirTimePanicThreshold; - if (panicThresh > 0.0f && fHuBrain->fCallbackAction->GetAirTime() > panicThresh) + if (panicThresh > 0.0f && fHuBrain->fWalkingStrategy->GetAirTime() > panicThresh) { fHuBrain->IdleOnly(); // clear the fall state; we're going somewhere new fAvMod->PanicLink(); @@ -1327,7 +1322,7 @@ void Push::Process(double time, float elapsed) fAvMod->GetPositionAndRotationSim(&pos, &rot); hsPoint3 lookAt; - fHuBrain->fCallbackAction->GetPushingPhysical()->GetPositionSim(lookAt); + fHuBrain->fWalkingStrategy->GetPushingPhysical()->GetPositionSim(lookAt); hsVector3 up(0.f, 0.f, 1.f); hsScalar angle = hsATan2(lookAt.fY - pos.fY, lookAt.fX - pos.fX) + hsScalarPI / 2; hsQuat targRot(angle, &up); @@ -1341,23 +1336,23 @@ void Push::Process(double time, float elapsed) globFwd = rot.Rotate(&globFwd); if (globFwd.fX < 0) - fHuBrain->fCallbackAction->SetTurnStrength(-turnSpeed); + fHuBrain->fWalkingStrategy->SetTurnStrength(-turnSpeed); else - fHuBrain->fCallbackAction->SetTurnStrength(turnSpeed); + fHuBrain->fWalkingStrategy->SetTurnStrength(turnSpeed); } //hsBool PushIdle::PreCondition(double time, float elapsed) //{ -// return (fHuBrain->fCallbackAction->GetPushingPhysical() && -// fHuBrain->fCallbackAction->IsOnGround() && +// return (fHuBrain->fWalkingStrategy->GetPushingPhysical() && +// fHuBrain->fWalkingStrategy->IsOnGround() && // !fAvMod->TurnLeftKeyDown() && !fAvMod->TurnRightKeyDown() // && fAvMod->GetTurnStrength() == 0); //} hsBool PushWalk::PreCondition(double time, float elapsed) { - return (fHuBrain->fCallbackAction->GetPushingPhysical() && fHuBrain->fCallbackAction->GetFacingPushingPhysical() && - fHuBrain->fCallbackAction->IsOnGround() && + return (fHuBrain->fWalkingStrategy->GetPushingPhysical() && fHuBrain->fWalkingStrategy->GetFacingPushingPhysical() && + fHuBrain->fWalkingStrategy->IsOnGround() && fAvMod->ForwardKeyDown()); } @@ -1372,7 +1367,7 @@ bool PushSimpleMultiStage(plArmatureMod *avatar, const char *enterAnim, const ch { plAvBrainHuman *huBrain = plAvBrainHuman::ConvertNoRef(avatar->FindBrainByClass(plAvBrainHuman::Index())); const char *names[3] = {enterAnim, idleAnim, exitAnim}; - if (!huBrain || !huBrain->fCallbackAction->IsOnGround() || !huBrain->fCallbackAction->HitGroundInThisAge() || huBrain->IsRunningTask() || + if (!huBrain || !huBrain->fWalkingStrategy->IsOnGround() || !huBrain->fWalkingStrategy->HitGroundInThisAge() || huBrain->IsRunningTask() || !avatar->IsPhysicsEnabled() || avatar->FindMatchingGenericBrain(names, 3)) return false; @@ -1436,7 +1431,7 @@ bool AvatarEmote(plArmatureMod *avatar, const char *emoteName) if (swimBrain && swimBrain->IsSwimming()) return false; - if (huBrain && huBrain->fCallbackAction->IsOnGround() && huBrain->fCallbackAction->HitGroundInThisAge() && !huBrain->IsRunningTask() && + if (huBrain && huBrain->fWalkingStrategy->IsOnGround() && huBrain->fWalkingStrategy->HitGroundInThisAge() && !huBrain->IsRunningTask() && emote && !alreadyActive && avatar->IsPhysicsEnabled()) { plKey avKey = avatar->GetKey(); diff --git a/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvBrainHuman.h b/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvBrainHuman.h index 008c0324..1544d151 100644 --- a/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvBrainHuman.h +++ b/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvBrainHuman.h @@ -58,7 +58,7 @@ class plAGAnimInstance; class plAvTask; class plAvTaskMsg; class plAvBrainHuman; -class plWalkingController; +class plWalkingStrategy; class plArmatureUpdateMsg; class plClimbMsg; class plControlEventMsg; @@ -164,7 +164,7 @@ public: static const hsScalar kControlledFlightThreshold; static const hsScalar kAirTimeThreshold; static const hsScalar kAirTimePanicThreshold; - plWalkingController* fCallbackAction; + plWalkingStrategy* fWalkingStrategy; protected: plAGAnim *FindCustomAnim(const char *baseName); diff --git a/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvBrainRideAnimatedPhysical.cpp b/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvBrainRideAnimatedPhysical.cpp index 85a1d975..8c71b456 100644 --- a/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvBrainRideAnimatedPhysical.cpp +++ b/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvBrainRideAnimatedPhysical.cpp @@ -44,7 +44,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com #include "plAvBrainHuman.h" #include "plAvBrain.h" -#include "plAvCallbackAction.h" +#include "plPhysicalControllerCore.h" #include "../plMessage/plRideAnimatedPhysMsg.h" @@ -52,20 +52,19 @@ void plAvBrainRideAnimatedPhysical::Activate(plArmatureModBase *avMod) { plArmatureBrain::Activate(avMod); IInitAnimations(); - if (!fCallbackAction) + if (!fWalkingStrategy) { plSceneObject* avObj = fArmature->GetTarget(0); plAGModifier* agMod = const_cast(plAGModifier::ConvertNoRef(FindModifierByClass(avObj, plAGModifier::Index()))); plPhysicalControllerCore* controller = avMod->GetController(); - fCallbackAction = TRACKED_NEW plRidingAnimatedPhysicalController(avObj, agMod->GetApplicator(kAGPinTransform), controller); - fCallbackAction->ActivateController(); + fWalkingStrategy = TRACKED_NEW plDynamicWalkingStrategy(agMod->GetApplicator(kAGPinTransform), controller); + controller->SetMovementStrategy(fWalkingStrategy); } } plAvBrainRideAnimatedPhysical::~plAvBrainRideAnimatedPhysical() { - delete fCallbackAction; - fCallbackAction=nil; - + delete fWalkingStrategy; + fWalkingStrategy = nil; } void plAvBrainRideAnimatedPhysical::Deactivate() diff --git a/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvBrainRideAnimatedPhysical.h b/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvBrainRideAnimatedPhysical.h index 6e02bbe2..520dfb96 100644 --- a/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvBrainRideAnimatedPhysical.h +++ b/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvBrainRideAnimatedPhysical.h @@ -41,8 +41,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com *==LICENSE==*/ #include "plAvBrainHuman.h" -class plRidingAnimatedPhysicalController; - class plAvBrainRideAnimatedPhysical : public plAvBrainHuman { public: diff --git a/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvBrainSwim.cpp b/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvBrainSwim.cpp index 3f0bd8ca..1499b36f 100644 --- a/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvBrainSwim.cpp +++ b/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvBrainSwim.cpp @@ -46,10 +46,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com // ///////////////////////////////////////////////////////////////////////////////////////// -//#include -//#include -#include "plAntiGravAction.h" // descends from Havok class, so must be included first, like havok objects - // singular #include "plAvBrainSwim.h" @@ -69,7 +65,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com #include "hsTimer.h" #include "plPhysical.h" #include "plPhysicalControllerCore.h" -#include "plAvCallbackAction.h" // other #include "../plPhysical/plCollisionDetector.h" #include "../plPipeline/plDebugText.h" @@ -180,18 +175,16 @@ public: static const float timeToMaxTurn = 0.5f; static const float incPerSec = maxTurnSpeed / timeToMaxTurn; -// hsAssert(0, "fixme physx"); - float oldSpeed = fabs(fSwimBrain->fCallbackAction->GetTurnStrength()); + float oldSpeed = fabs(fSwimBrain->fSwimStrategy->GetTurnStrength()); float thisInc = elapsed * incPerSec; float newSpeed = __min(oldSpeed + thisInc, maxTurnSpeed); - fSwimBrain->fCallbackAction->SetTurnStrength(newSpeed * fAvMod->GetKeyTurnStrength() + fAvMod->GetAnalogTurnStrength()); + fSwimBrain->fSwimStrategy->SetTurnStrength(newSpeed * fAvMod->GetKeyTurnStrength() + fAvMod->GetAnalogTurnStrength()); // the turn is actually applied during PhysicsUpdate } virtual void IStop() { -// hsAssert(0, "fixme physx"); - if (fSwimBrain->fCallbackAction) - fSwimBrain->fCallbackAction->SetTurnStrength(0.0f); + if (fSwimBrain->fSwimStrategy) + fSwimBrain->fSwimStrategy->SetTurnStrength(0.0f); plSwimBehavior::IStop(); } }; @@ -237,7 +230,7 @@ public: const hsScalar plAvBrainSwim::kMinSwimDepth = 4.0f; plAvBrainSwim::plAvBrainSwim() : - fCallbackAction(nil), + fSwimStrategy(nil), fMode(kWalking), fSurfaceDistance(0.f) { @@ -250,12 +243,9 @@ plAvBrainSwim::plAvBrainSwim() : plAvBrainSwim::~plAvBrainSwim() { - if(fCallbackAction) - { - IDetachAction(); - delete fCallbackAction; - fCallbackAction=nil; - } + delete fSwimStrategy; + fSwimStrategy = nil; + fSurfaceProbeMsg->UnRef(); int i; @@ -273,8 +263,7 @@ hsBool plAvBrainSwim::Apply(double time, hsScalar elapsed) fMode = kWading; plAvBrainHuman *huBrain = plAvBrainHuman::ConvertNoRef(fAvMod->GetNextBrain(this)); -// hsAssert(0, "fixme physx"); - if (huBrain && !huBrain->fCallbackAction->IsOnGround()) + if (huBrain && !huBrain->fWalkingStrategy->IsOnGround()) { // We're jumping in! Trigger splash effect (sound) plArmatureEffectMsg *msg = TRACKED_NEW plArmatureEffectMsg(fAvMod->GetArmatureEffects()->GetKey(), kTime); @@ -318,8 +307,7 @@ hsBool plAvBrainSwim::Apply(double time, hsScalar elapsed) // The contact check is so that if buoyancy bobs us a little too high, we don't // switch to wading only to fall again. -// hsAssert(0, "fixme physx"); - if (fSurfaceDistance < kMinSwimDepth-.5 && fCallbackAction->HadContacts()) + if (fSurfaceDistance < kMinSwimDepth-.5 && fSwimStrategy->HadContacts()) IStartWading(); } else if (fMode == kSwimming3D) @@ -346,13 +334,12 @@ hsBool plAvBrainSwim::MsgReceive(plMessage *msg) else fSurfaceDistance = -100.f; -// hsAssert(0, "fixme physx"); - if (fCallbackAction) + if (fSwimStrategy) { if (region) - fCallbackAction->SetSurface(region, fArmature->GetTarget(0)->GetLocalToWorld().GetTranslate().fZ + fSurfaceDistance); + fSwimStrategy->SetSurface(region, fArmature->GetTarget(0)->GetLocalToWorld().GetTranslate().fZ + fSurfaceDistance); else - fCallbackAction->SetSurface(nil, 0.f); + fSwimStrategy->SetSurface(nil, 0.f); } return true; } @@ -419,20 +406,16 @@ void plAvBrainSwim::Activate(plArmatureModBase* avMod) void plAvBrainSwim::Deactivate() { plArmatureBrain::Deactivate(); - - IDetachAction(); } void plAvBrainSwim::Suspend() { - if (fMode == kSwimming2D) - IDetachAction(); } void plAvBrainSwim::Resume() { if (fMode == kSwimming2D) - IAttachAction(); + fSwimStrategy->Reset(false); } bool plAvBrainSwim::IsWalking() @@ -460,8 +443,6 @@ void plAvBrainSwim::IStartWading() for (i = 0; i < fBehaviors.GetCount(); i++) fBehaviors[i]->SetStrength(0.f, 2.f); - IDetachAction(); - if (fAvMod->IsLocalAvatar()) { plCameraMsg* pMsg = TRACKED_NEW plCameraMsg; @@ -479,7 +460,16 @@ void plAvBrainSwim::IStartSwimming(bool is2D) plArmatureBrain *nextBrain = fAvMod->GetNextBrain(this); nextBrain->Suspend(); - IAttachAction(); + if (!fSwimStrategy) + { + plSceneObject * avObj = fArmature->GetTarget(0); + plAGModifier *agMod = const_cast(plAGModifier::ConvertNoRef(FindModifierByClass(avObj, plAGModifier::Index()))); + plPhysicalControllerCore *controller = fAvMod->GetController(); + fSwimStrategy = new plSwimStrategy(agMod->GetApplicator(kAGPinTransform), controller); + } + + fSwimStrategy->Reset(false); + if (is2D) fMode = kSwimming2D; else @@ -509,8 +499,8 @@ hsBool plAvBrainSwim::IProcessSwimming2D(double time, float elapsed) else behavior->SetStrength(0.f, 2.f); } -// hsAssert(0, "fixme physx"); - fCallbackAction->RecalcVelocity(time, time - elapsed); + + fSwimStrategy->RecalcVelocity(time, elapsed); return true; } @@ -568,59 +558,6 @@ hsBool plAvBrainSwim::IInitAnimations() return true; } -bool plAvBrainSwim::IAttachAction() -{ - bool result = false; - if(fAvMod) - { -// hsAssert(0, "fixme physx"); - plPhysicalControllerCore *physical = fAvMod->GetController(); - - if (physical) - { - if (!fCallbackAction) - { - plSceneObject * avObj = fArmature->GetTarget(0); - plAGModifier *agMod = const_cast(plAGModifier::ConvertNoRef(FindModifierByClass(avObj, plAGModifier::Index()))); - fCallbackAction = new plSwimmingController(avObj, agMod->GetApplicator(kAGPinTransform),physical); -// physical->AttachAction(fCallbackAction, true, false); - result = true; - } - else - { - fCallbackAction->ActivateController(); - } - - } - } - return result; -} - -bool plAvBrainSwim::IDetachAction() -{ - bool result = false; - - if (fCallbackAction) - { -// hsAssert(0, "fixme physx"); -// plPhysical *physical = fAvMod->GetPhysical(); -// -// if(physical) -// { -// physical->RemoveAction(fCallbackAction); -// result = true; // there was an action and we removed it -// } - - // TODO: We get a compiler warning about deleting a pointer to an - // undefined class. So, who knows what the code is actually doing. - // Seems bad. Just putting a note in here for whoever fixes the - // physx issue. - //delete fCallbackAction; - //fCallbackAction = nil; - } - return result; -} - void plAvBrainSwim::IProbeSurface() { hsPoint3 ourPos = fAvMod->GetTarget(0)->GetLocalToWorld().GetTranslate(); @@ -676,21 +613,15 @@ void plAvBrainSwim::DumpToDebugDisplay(int &x, int &y, int lineHeight, char *str debugTxt.DrawString(x, y, strBuf); y += lineHeight; + float buoy = fSwimStrategy ? fSwimStrategy->GetBuoyancy() : 0.0f; + sprintf(strBuf, "Distance to surface: %f Buoyancy: %f", fSurfaceDistance, buoy); + debugTxt.DrawString(x, y, strBuf); + y += lineHeight; -// hsAssert(0, "fixme physx"); -// float buoy = fCallbackAction? fCallbackAction->GetBuoyancy() : 0.0f; -// sprintf(strBuf, "Distance to surface: %f Buoyancy: %f", fSurfaceDistance, buoy); -// debugTxt.DrawString(x, y, strBuf); -// y += lineHeight; -// -// hsVector3 linV; -// fAvMod->GetPhysical()->GetLinearVelocitySim(linV); -// hsVector3 angV; -// fAvMod->GetPhysical()->GetAngularVelocitySim(angV); -// hsScalar angle = angV.fZ > 0 ? angV.Magnitude() : -angV.Magnitude(); -// sprintf(strBuf, "Velocity: Linear (%5.2f, %5.2f, %5.2f), Angular %5.2f", linV.fX, linV.fY, linV.fZ, angle); -// debugTxt.DrawString(x, y, strBuf); -// y += lineHeight; + hsVector3 linV = fAvMod->GetController()->GetAchievedLinearVelocity(); + sprintf(strBuf, "Linear Velocity: (%5.2f, %5.2f, %5.2f)", linV.fX, linV.fY, linV.fZ); + debugTxt.DrawString(x, y, strBuf); + y += lineHeight; int i; for (i = 0; i < fBehaviors.GetCount(); i++) diff --git a/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvBrainSwim.h b/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvBrainSwim.h index b75651ef..d3e9f83b 100644 --- a/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvBrainSwim.h +++ b/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvBrainSwim.h @@ -47,11 +47,10 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com #include "../pnKeyedObject/plKey.h" class plArmatureMod; -class plAntiGravAction; class plControlEventMsg; class plLOSRequestMsg; class plSwimRegionInterface; -class plSwimmingController; +class plSwimStrategy; class plAvBrainSwim : public plArmatureBrain { public: @@ -73,7 +72,7 @@ public: bool IsSwimming(); hsScalar GetSurfaceDistance() { return fSurfaceDistance; } - plSwimmingController *fCallbackAction; + plSwimStrategy *fSwimStrategy; static const hsScalar kMinSwimDepth; protected: @@ -86,8 +85,6 @@ protected: hsBool IProcessBehaviors(double time, float elapsed); virtual hsBool IInitAnimations(); - bool IAttachAction(); - bool IDetachAction(); void IProbeSurface(); hsBool IHandleControlMsg(plControlEventMsg* msg); float IGetTargetZ(); diff --git a/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvCallbackAction.cpp b/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvCallbackAction.cpp deleted file mode 100644 index c192f3b9..00000000 --- a/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvCallbackAction.cpp +++ /dev/null @@ -1,579 +0,0 @@ -/*==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 . - -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 "plAvCallbackAction.h" -#include "../plMessage/plLOSHitMsg.h" - -#include "plArmatureMod.h" // for LOS enum type -#include "plMatrixChannel.h" -#include "hsTimer.h" -#include "plPhysicalControllerCore.h" - -// Generic geom utils. -hsBool LinearVelocity(hsVector3 &outputV, float elapsed, hsMatrix44 &prevMat, hsMatrix44 &curMat); -void AngularVelocity(hsScalar &outputV, float elapsed, hsMatrix44 &prevMat, hsMatrix44 &curMat); -float AngleRad2d (float x1, float y1, float x3, float y3); -inline hsVector3 GetYAxis(hsMatrix44 &mat) -{ - return hsVector3(mat.fMap[1][0], mat.fMap[1][1], mat.fMap[1][2]); -} - -plAnimatedController::plAnimatedController(plSceneObject* rootObject, plAGApplicator* rootApp, plPhysicalControllerCore* controller) - : fRootObject(rootObject) - , fRootApp(rootApp) - , fController(controller) - , fTurnStr(0.f) - , fAnimAngVel(0.f) - , fAnimPosVel(0.f, 0.f, 0.f) -{ -} - -void plAnimatedController::RecalcVelocity(double timeNow, double timePrev, hsBool useAnim /* = true */) -{ - if (useAnim) - { - // while you may think it would be correct to cache this, - // what we're actually asking is "what would the animation's - // position be at the previous time given its *current* - // parameters (particularly blends)" - hsMatrix44 prevMat = ((plMatrixChannel *)fRootApp->GetChannel())->Value(timePrev, true); - hsMatrix44 curMat = ((plMatrixChannel *)fRootApp->GetChannel())->Value(timeNow, true); - - // If we get a valid linear velocity (ie, we didn't wrap around in the anim), - // use it. Otherwise just reuse the previous frames velocity. - hsVector3 linearVel; - if (LinearVelocity(linearVel, (float)(timeNow - timePrev), prevMat, curMat)) - fAnimPosVel = linearVel; - - // Automatically sets fAnimAngVel - AngularVelocity(fAnimAngVel, (float)(timeNow - timePrev), prevMat, curMat); - } - else - { - fAnimPosVel.Set(0.f, 0.f, 0.f); - fAnimAngVel = 0.f; - } - - if (fController) - fController->SetVelocities(fAnimPosVel, fAnimAngVel + fTurnStr); -} - -/////////////////////////////////////////////////////////////////////////// - -const hsScalar plWalkingController::kControlledFlightThreshold = 1.f; // seconds - -plWalkingController::plWalkingController(plSceneObject* rootObject, plAGApplicator* rootApp, plPhysicalControllerCore* controller) - : plAnimatedController(rootObject, rootApp, controller) - , fHitGroundInThisAge(false) - , fWaitingForGround(false) - , fControlledFlightTime(0) - , fControlledFlight(0) - , fImpactTime(0.f) - , fImpactVelocity(0.f, 0.f, 0.f) - , fClearImpact(false) - , fGroundLastFrame(false) -{ - if (fController) - { - fWalkingStrategy= TRACKED_NEW plWalkingStrategy(fController); - fController->SetMovementSimulationInterface(fWalkingStrategy); - } - else - fWalkingStrategy = nil; -} - -void plWalkingController::RecalcVelocity(double timeNow, double timePrev, hsBool useAnim) -{ - if (!fHitGroundInThisAge && fController && fController->IsEnabled() && fWalkingStrategy->IsOnGround()) - fHitGroundInThisAge = true; // if we're not pinned and we're not in an age yet, we are now. - - if (fClearImpact) - { - fImpactTime = 0.f; - fImpactVelocity.Set(0.f, 0.f, 0.f); - } - - if (fController && !fWalkingStrategy->IsOnGround()) - { - // PhysX Hack - // LinearVelocity is always (0,0,0) outside the PhysController - fImpactTime = fWalkingStrategy->GetAirTime(); - fImpactVelocity = fController->GetAchievedLinearVelocity(); - // convert orientation from subworld to avatar-local coordinates - fImpactVelocity = (hsVector3)fController->GetLocalRotation().Rotate(&fImpactVelocity); - fClearImpact = false; - } - else - fClearImpact = true; - - if (IsControlledFlight()) - { - if (fWalkingStrategy && fWalkingStrategy->IsOnGround()) - fControlledFlightTime = fWalkingStrategy->GetAirTime(); - if(fGroundLastFrame&&(fWalkingStrategy && !fWalkingStrategy->IsOnGround())) - { - //we have started to leave the ground tell the movement strategy in case it cares - fWalkingStrategy->StartJump(); - } - if (fControlledFlightTime > kControlledFlightThreshold) - EnableControlledFlight(false); - } - if (fWalkingStrategy) - fGroundLastFrame = fWalkingStrategy->IsOnGround(); - else - fGroundLastFrame=false; - plAnimatedController::RecalcVelocity(timeNow, timePrev, useAnim); -} - -void plWalkingController::Reset(bool newAge) -{ - - ActivateController(); - if (newAge) - { - if (fWalkingStrategy) - fWalkingStrategy->ResetAirTime(); - fHitGroundInThisAge = false; - } -} - void plWalkingController::ActivateController() -{ - if (fWalkingStrategy) - { - fWalkingStrategy->RefreshConnectionToControllerCore(); - } - else - { - fWalkingStrategy= TRACKED_NEW plWalkingStrategy(fController); - fWalkingStrategy->RefreshConnectionToControllerCore(); - - } -} - -bool plWalkingController::EnableControlledFlight(bool status) -{ - if (status) - { - if (fControlledFlight == 0) - fControlledFlightTime = 0.f; - - ++fControlledFlight; - fWaitingForGround = true; - } - else - fControlledFlight = __max(--fControlledFlight, 0); - - return status; -} -plWalkingController::~plWalkingController() -{ - delete fWalkingStrategy; - if (fController) - fController->SetMovementSimulationInterface(nil); -} -#if 0 -void plWalkingController::Update() -{ -// double elapsed = time.asDouble() - getRefresh().asDouble(); -// setRefresh(time); -// -// hsBool isPhysical = !fPhysical->GetProperty(plSimulationInterface::kPinned); -// const Havok::Vector3 straightUp(0.0f, 0.0f, 1.0f); -// hsBool alreadyInAge = fHitGroundInThisAge; -// -// int numContacts = fPhysical->GetNumContacts(); -// bool ground = false; -// fPushingPhysical = nil; -// int i, j; - -/* for(i = 0; i < numContacts; i++) - { - plHKPhysical *contactPhys = fPhysical->GetContactPhysical(i); - if (!contactPhys) - continue; // Physical no longer exists. Skip it. - - const Havok::ContactPoint *contact = fPhysical->GetContactPoint(i); - hsScalar dotUp = straightUp.dot(contact->m_normal); - if (dotUp > .5) - ground = true; - else if (contactPhys->GetProperty(plSimulationInterface::kAvAnimPushable)) - { - hsPoint3 position; - hsQuat rotation; - fPhysical->GetPositionAndRotationSim(&position, &rotation); - - hsQuat inverseRotation = rotation.Inverse(); - hsVector3 normal(contact->m_normal.x, contact->m_normal.y, contact->m_normal.z); - fFacingPushingPhysical = (inverseRotation.Rotate(&kAvatarForward).InnerProduct(normal) < 0 ? true : false); - - fPushingPhysical = contactPhys; - } - } - - // We need to check for the case where the avatar hasn't collided with "ground", but is colliding - // with a few other objects so that he's not actually falling (wedged in between some slopes). - // We do this by answering the following question (in 2d top-down space): "If you sort the contact - // normals by angle, is there a large enough gap between normals?" - // - // If you think in terms of geometry, this means a collection of surfaces are all pushing on you. - // If they're pushing from all sides, you have nowhere to go, and you won't fall. There needs to be - // a gap, so that you're pushed out and have somewhere to fall. This is the same as finding a gap - // larger than 180 degrees between sorted normals. - // - // The problem is that on top of that, the avatar needs enough force to shove him out that gap (he - // has to overcome friction). I deal with that by making the threshold (360 - (180 - 60) = 240). I've - // seen up to 220 reached in actual gameplay in a situation where we'd want this to take effect. - // This is the same running into 2 walls where the angle between them is 60. - const hsScalar threshold = hsScalarDegToRad(240); - if (!ground && numContacts >= 2) - { - // Can probably do a special case for exactly 2 contacts. Not sure if it's worth it... - - fCollisionAngles.SetCount(numContacts); - for (i = 0; i < numContacts; i++) - { - const Havok::ContactPoint *contact = fPhysical->GetContactPoint(i); - fCollisionAngles[i] = hsATan2(contact->m_normal.y, contact->m_normal.x); - } - - // numContacts is rarely larger than 6, so let's do a simple bubble sort. - for (i = 0; i < numContacts; i++) - { - for (j = i + 1; j < numContacts; j++) - { - if (fCollisionAngles[i] > fCollisionAngles[j]) - { - hsScalar tempAngle = fCollisionAngles[i]; - fCollisionAngles[i] = fCollisionAngles[j]; - fCollisionAngles[j] = tempAngle; - } - } - } - - // sorted, now we check. - for (i = 1; i < numContacts; i++) - { - if (fCollisionAngles[i] - fCollisionAngles[i - 1] >= threshold) - break; - } - - if (i == numContacts) - { - // We got to the end. Check the last with the first and make your decision. - if (!(fCollisionAngles[0] - fCollisionAngles[numContacts - 1] >= (threshold - 2 * hsScalarPI))) - ground = true; - } - } -*/ - - bool ground = fController ? fController->GotGroundHit() : true; - bool isPhysical = true; - - if (!fHitGroundInThisAge && isPhysical) - fHitGroundInThisAge = true; // if we're not pinned and we're not in an age yet, we are now. - - if (IsControlledFlight()) - fControlledFlightTime += (hsScalar)elapsed; - if (fControlledFlightTime > kControlledFlightThreshold && numContacts > 0) - EnableControlledFlight(false); - - if (ground || !isPhysical) - { - if (!IsControlledFlight() && !IsOnGround()) - { - // The first ground contact in an age doesn't count. -// if (alreadyInAge) -// { -// hsVector3 vel; -// fPhysical->GetLinearVelocitySim(vel); -// fImpactVel = vel.fZ; -// fTimeInAirPeak = (hsScalar)(fTimeInAir + elapsed); -// } - - fWaitingForGround = false; - } - fTimeInAir = 0; - } - else if (elapsed < plSimulationMgr::GetInstance()->GetMaxDelta()) - { - // If the simultation skipped a huge chunk of time, we didn't process the - // collisions, which could trick us into thinking we've just gone a long - // time without hitting ground. So we only count the time if this wasn't - // the case. - fTimeInAir += (hsScalar)elapsed; - } - - - // Tweakage so that we still fall under the right conditions. - // If we're in controlled flight, or standing still with ground solidly under us (probe hit). We only use anim velocity. -// if (!IsControlledFlight() && !(ground && fProbeHitGround && fAnimPosVel.fX == 0 && fAnimPosVel.fY == 0)) -// { -// hsVector3 curV; -// fPhysical->GetLinearVelocitySim(curV); -// fAnimPosVel.fZ = curV.fZ; -// -// // Prevents us from going airborn from running up bumps/inclines. -// if (IsOnGround() && fAnimPosVel.fZ > 0.f) -// fAnimPosVel.fZ = 0.f; -// -// // Unless we're on the ground and moving, or standing still with a probe hit, we use the sim's other axes too. -// if (!(IsOnGround() && (fProbeHitGround || fAnimPosVel.fX != 0 || fAnimPosVel.fY != 0))) -// { -// fAnimPosVel.fX = curV.fX; -// fAnimPosVel.fY = curV.fY; -// } -// } -// -// fPhysical->SetLinearVelocitySim(fAnimPosVel); -// fPhysical->SetSpin(fAnimAngVel + fTurnStr, hsVector3(0.0f, 0.0f, 1.0f)); -} -#endif - - -#if 0 - -///////////////////////////////////////////////////////////////////////// - -plSimDefs::ActionType plHorizontalFreezeAction::GetType() -{ - return plSimDefs::kHorizontalFreeze; -} - -void plHorizontalFreezeAction::apply(Havok::Subspace &s, Havok::hkTime time) -{ - double elapsed = time.asDouble() - getRefresh().asDouble(); - setRefresh(time); - - int numContacts = fPhysical->GetNumContacts(); - bool ground = false; - const Havok::Vector3 straightUp(0.0f, 0.0f, 1.0f); - int i; - for(i = 0; i < numContacts; i++) - { - const Havok::ContactPoint *contact = fPhysical->GetContactPoint(i); - hsScalar dotUp = straightUp.dot(contact->m_normal); - if (dotUp > .5) - ground = true; - } - - hsVector3 vel; - fPhysical->GetLinearVelocitySim(vel); - vel.fX = 0.0; - vel.fY = 0.0; - if (ground) - vel.fZ = 0; - fPhysical->SetLinearVelocitySim(vel); - fPhysical->ClearContacts(); -} -#endif -plSwimmingController::plSwimmingController(plSceneObject* rootObject, plAGApplicator* rootApp, plPhysicalControllerCore* controller) -:plAnimatedController(rootObject,rootApp,controller) -{ - if (controller) - fSwimmingStrategy= TRACKED_NEW plSwimStrategy(controller); - else - fSwimmingStrategy = nil; -} -plSwimmingController::~plSwimmingController() -{ - delete fSwimmingStrategy; -} - -plRidingAnimatedPhysicalController::plRidingAnimatedPhysicalController(plSceneObject* rootObject, plAGApplicator* rootApp, plPhysicalControllerCore* controller) -: plWalkingController(rootObject, rootApp, controller) -{ - if(controller) - fWalkingStrategy = TRACKED_NEW plRidingAnimatedPhysicalStrategy(controller); - else - fWalkingStrategy = nil; -} -plRidingAnimatedPhysicalController::~plRidingAnimatedPhysicalController() -{ - delete fWalkingStrategy; - fWalkingStrategy=nil; -} - - -////////////////////////////////////////////////////////////////////////// - - -/* -Purpose: - -ANGLE_RAD_2D returns the angle in radians swept out between two rays in 2D. - -Discussion: - -Except for the zero angle case, it should be true that - -ANGLE_RAD_2D(X1,Y1,X2,Y2,X3,Y3) -+ ANGLE_RAD_2D(X3,Y3,X2,Y2,X1,Y1) = 2 * PI - -Modified: - -19 April 1999 - -Author: - -John Burkardt - -Parameters: - -Input, float X1, Y1, X2, Y2, X3, Y3, define the rays -( X1-X2, Y1-Y2 ) and ( X3-X2, Y3-Y2 ) which in turn define the -angle, counterclockwise from ( X1-X2, Y1-Y2 ). - -Output, float ANGLE_RAD_2D, the angle swept out by the rays, measured -in radians. 0 <= ANGLE_DEG_2D < 2 PI. If either ray has zero length, -then ANGLE_RAD_2D is set to 0. -*/ - -static float AngleRad2d ( float x1, float y1, float x3, float y3 ) -{ - float value; - float x; - float y; - - x = ( x1 ) * ( x3 ) + ( y1 ) * ( y3 ); - y = ( x1 ) * ( y3 ) - ( y1 ) * ( x3 ); - - if ( x == 0.0 && y == 0.0 ) { - value = 0.0; - } - else - { - value = atan2 ( y, x ); - - if ( value < 0.0 ) - { - value = (float)(value + TWO_PI); - } - } - return value; -} - -static hsBool LinearVelocity(hsVector3 &outputV, float elapsed, hsMatrix44 &prevMat, hsMatrix44 &curMat) -{ - bool result = false; - - hsPoint3 startPos(0.0f, 0.0f, 0.0f); // default position (at start of anim) - hsPoint3 prevPos = prevMat.GetTranslate(); // position previous frame - hsPoint3 nowPos = curMat.GetTranslate(); // position current frame - - hsVector3 prev2Now = (hsVector3)(nowPos - prevPos); // frame-to-frame delta - - if (fabs(prev2Now.fX) < 0.0001f && fabs(prev2Now.fY) < 0.0001f && fabs(prev2Now.fZ) < 0.0001f) - { - outputV.Set(0.f, 0.f, 0.f); - result = true; - } - else - { - hsVector3 start2Now = (hsVector3)(nowPos - startPos); // start-to-frame delta - - float prev2NowMagSqr = prev2Now.MagnitudeSquared(); - float start2NowMagSqr = start2Now.MagnitudeSquared(); - - float dot = prev2Now.InnerProduct(start2Now); - - // HANDLING ANIMATION WRAPPING: - // the vector from the animation origin to the current frame should point in roughly - // the same direction as the vector from the previous animation position to the - // current animation position. - // - // If they don't agree (dot < 0,) then we probably mpst wrapped around. - // The right answer would be to compare the current frame to the start of - // the anim loop, but it's cheaper to cheat and return false, - // telling the caller to use the previous frame's velocity. - if (dot > 0.0f) - { - prev2Now /= elapsed; - - float xfabs = fabs(prev2Now.fX); - float yfabs = fabs(prev2Now.fY); - float zfabs = fabs(prev2Now.fZ); - static const float maxVel = 20.0f; - hsBool valid = xfabs < maxVel && yfabs < maxVel && zfabs < maxVel; - - if (valid) - { - outputV = prev2Now; - result = true; - } - } - } - - return result; -} - -static void AngularVelocity(hsScalar &outputV, float elapsed, hsMatrix44 &prevMat, hsMatrix44 &curMat) -{ - outputV = 0.f; - hsScalar appliedVelocity = 0.0f; - hsVector3 prevForward = GetYAxis(prevMat); - hsVector3 curForward = GetYAxis(curMat); - - hsScalar angleSincePrev = AngleRad2d(curForward.fX, curForward.fY, prevForward.fX, prevForward.fY); - hsBool sincePrevSign = angleSincePrev > 0.0f; - if (angleSincePrev > hsScalarPI) - angleSincePrev = angleSincePrev - TWO_PI; - - const hsVector3 startForward = hsVector3(0, -1.0, 0); // the Y orientation of a "resting" armature.... - hsScalar angleSinceStart = AngleRad2d(curForward.fX, curForward.fY, startForward.fX, startForward.fY); - hsBool sinceStartSign = angleSinceStart > 0.0f; - if (angleSinceStart > hsScalarPI) - angleSinceStart = angleSinceStart - TWO_PI; - - // HANDLING ANIMATION WRAPPING: - // under normal conditions, the angle from rest to the current frame will have the same - // sign as the angle from the previous frame to the current frame. - // if it does not, we have (most likely) wrapped the motivating animation from frame n back - // to frame zero, creating a large angle from the previous frame to the current one - if (sincePrevSign == sinceStartSign) - { - // signs are the same; didn't wrap; use the frame-to-frame angle difference - appliedVelocity = angleSincePrev / elapsed; // rotation / time - if (fabs(appliedVelocity) < 3) - { - outputV = appliedVelocity; - } - } -} diff --git a/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvCallbackAction.h b/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvCallbackAction.h deleted file mode 100644 index c4e374ba..00000000 --- a/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvCallbackAction.h +++ /dev/null @@ -1,217 +0,0 @@ -/*==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 . - -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==*/ -#ifndef PL_HK_CALLBACK_ACTION_H -#define PL_HK_CALLBACK_ACTION_H - -#include "hsGeometry3.h" -#include "hsMatrix44.h" -#include "hsTemplates.h" -#include "../pnKeyedObject/plKey.h" -#include "../plPhysical/plSimDefs.h" -#include "../pnMessage/plMessage.h" -#include "plPhysicalControllerCore.h" -class plLOSHitMsg; -class plAGApplicator; -class plSceneObject; -class plPhysical; -class plAvatarController; -class plCoordinateInterface; -class plPhysicalControllerCore; -// Used by the other controllers to actually move the avatar. The actual -// implementation is in the physics system. -/*class plPhysicalController -{ -public: - // Implemented in the physics system. If you're linking this without that for - // some reason, just stub this function out. - // - // Pass in the key to the root sceneobject for the avatar - static plPhysicalController* Create(plKey ownerSO, hsScalar height, hsScalar width); - - virtual ~plPhysicalController() {} - - // A disabled avatar doesn't move or accumulate air time if he's off the ground. - virtual void Enable(bool enable) = 0; - virtual bool IsEnabled() const = 0; - - // Set the LOS DB this avatar will be in (only one) - virtual void SetLOSDB(plSimDefs::plLOSDB losDB) = 0; - - // Call this once per frame with the velocities of the avatar in avatar space. - virtual void SetVelocities(const hsVector3& linearVel, hsScalar angVel) = 0; - - // Gets the actual velocity we achieved in the last step (relative to our subworld) - virtual const hsVector3& GetLinearVelocity() const = 0; - virtual void ResetAchievedLinearVelocity() = 0; - - // Get and set the current subworld for the avatar. Use nil for the main world. - virtual plKey GetSubworld() const = 0; - virtual void SetSubworld(plKey world) = 0; - - // If IsOnGround returns false, GetAirTime will tell you how long the avatar - // has been airborne. Use ResetAirTime to reset the air time to zero, for - // cases like when the avatar spawns into a new age. - virtual bool IsOnGround() const = 0; - virtual bool IsOnFalseGround() const = 0; - virtual hsScalar GetAirTime() const = 0; - virtual void ResetAirTime() = 0; - - virtual plPhysical* GetPushingPhysical() const = 0; - virtual bool GetFacingPushingPhysical() const = 0; - - // A helper function to get the coordinate interface for the avatars current - // world. Handy if you need to convert points to and from that. This will - // return nil if the avatar is in the main world (ie, you don't need to do - // any translation). - virtual const plCoordinateInterface* GetSubworldCI() const = 0; - - // For the avatar SDL only - virtual void GetState(hsPoint3& pos, float& zRot) = 0; - virtual void SetState(const hsPoint3& pos, float zRot) = 0; - - // kinematic stuff .... should be just for when playing a behavior... - virtual void Kinematic(bool state) = 0; - virtual bool IsKinematic() = 0; - virtual void GetKinematicPosition(hsPoint3& pos) = 0; - - virtual const hsMatrix44& GetPrevSubworldW2L() = 0; - - //when seeking no longer want to interact with exclusion regions - virtual void SetSeek(bool seek)=0; - - -}; -*/ -class plAvatarController -{ -public: - virtual ~plAvatarController() {} -}; - -class plAnimatedController : public plAvatarController -{ -public: - plAnimatedController(plSceneObject* rootObject, plAGApplicator* rootApp, plPhysicalControllerCore* controller); - - virtual void RecalcVelocity(double timeNow, double timePrev, hsBool useAnim = true); - void SetTurnStrength(hsScalar val) { fTurnStr = val; } - hsScalar GetTurnStrength() { return fTurnStr; } - virtual void ActivateController()=0; -protected: - plSceneObject* fRootObject; - plPhysicalControllerCore* fController; - plAGApplicator* fRootApp; - hsScalar fAnimAngVel; - hsVector3 fAnimPosVel; - hsScalar fTurnStr; // Explicit turning, separate from animations -}; - -class plWalkingController : public plAnimatedController -{ -public: - plWalkingController(plSceneObject* rootObject, plAGApplicator* rootApp, plPhysicalControllerCore* controller); - virtual ~plWalkingController(); - virtual void RecalcVelocity(double timeNow, double timePrev, hsBool useAnim = true); - - void Reset(bool newAge); - bool IsControlledFlight() const { return fControlledFlight != 0; } - bool IsOnGround() const { return fWalkingStrategy ? fWalkingStrategy->IsOnGround() : true; } - bool IsOnFalseGround() const { return fWalkingStrategy ? fWalkingStrategy->IsOnFalseGround() : true; } - bool HitGroundInThisAge() const { return fHitGroundInThisAge; } - bool EnableControlledFlight(bool status); - hsScalar GetAirTime() const { return fWalkingStrategy ? fWalkingStrategy->GetAirTime() : 0.f; } - void ResetAirTime() { if (fWalkingStrategy) fWalkingStrategy->ResetAirTime(); } - hsScalar GetForwardVelocity() const; - void ActivateController(); - // Check these after the avatar the avatar hits the ground for his total - // hangtime and impact velocity. - hsScalar GetImpactTime() const { return fImpactTime; } - const hsVector3& GetImpactVelocity() const { return fImpactVelocity; } - - plPhysical* GetPushingPhysical() const - { - if(fController)return fController->GetPushingPhysical(); - else return nil; - } - bool GetFacingPushingPhysical() const - { if(fController)return fController->GetFacingPushingPhysical(); - else return false; - } - - -protected: - bool fHitGroundInThisAge; - bool fWaitingForGround; // We've gone airborne. IsOnGround() returns false until we hit ground again. - hsScalar fControlledFlightTime; - int fControlledFlight; // Count of how many are currently forcing flight - plWalkingStrategy* fWalkingStrategy; - hsScalar fImpactTime; - hsVector3 fImpactVelocity; - bool fClearImpact; - bool fGroundLastFrame;//used for a test to pass the event of first getting air during a jump - static const hsScalar kControlledFlightThreshold; -}; -class plSwimmingController: public plAnimatedController -{ -public : - plSwimmingController(plSceneObject* rootObject, plAGApplicator* rootApp, plPhysicalControllerCore* controller); - virtual ~plSwimmingController(); - void SetSurface(plSwimRegionInterface *region, hsScalar surfaceHeight){ - fSwimmingStrategy->SetSurface(region,surfaceHeight); - } - hsScalar GetBuoyancy() { return fSwimmingStrategy->GetBuoyancy(); } - hsBool IsOnGround() { return fSwimmingStrategy->IsOnGround(); } - hsBool HadContacts() { return fSwimmingStrategy->HadContacts();} - void Enable(bool en){if (fController) fController->Enable(en);} - plPhysicalControllerCore* GetController(){return fController;} - virtual void ActivateController(){fSwimmingStrategy->RefreshConnectionToControllerCore();} -protected: - plSwimStrategy* fSwimmingStrategy; - -}; -class plRidingAnimatedPhysicalController: public plWalkingController -{ -public: - plRidingAnimatedPhysicalController(plSceneObject* rootObject, plAGApplicator* rootApp, plPhysicalControllerCore* controller); - virtual ~plRidingAnimatedPhysicalController(); -}; -#endif // PL_HK_CALLBACK_ACTION_H diff --git a/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvLadderModifier.cpp b/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvLadderModifier.cpp index f303c47f..2c214e92 100644 --- a/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvLadderModifier.cpp +++ b/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvLadderModifier.cpp @@ -39,7 +39,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com Mead, WA 99021 *==LICENSE==*/ -#include "../plAvatar/plAvCallbackAction.h" +#include "plPhysicalControllerCore.h" #include "hsTypes.h" @@ -129,7 +129,7 @@ bool plAvLadderMod::IIsReadyToClimb() if (armMod) { plAvBrainHuman* brain = plAvBrainHuman::ConvertNoRef(armMod->GetCurrentBrain()); - if (brain && brain->IsMovingForward() && brain->fCallbackAction->IsOnGround()) + if (brain && brain->IsMovingForward() && brain->fWalkingStrategy->IsOnGround()) movingForward = true; } diff --git a/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvTaskSeek.cpp b/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvTaskSeek.cpp index 3b70bca4..84b80cfe 100644 --- a/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvTaskSeek.cpp +++ b/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvTaskSeek.cpp @@ -54,7 +54,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com #include "plAGAnim.h" #include "plArmatureMod.h" #include "plAvatarMgr.h" -#include "plAvCallbackAction.h" +#include "plPhysicalControllerCore.h" // other #include "../plMessage/plAvatarMsg.h" @@ -462,10 +462,10 @@ hsBool plAvTaskSeek::IFinishPosition(hsPoint3 &newPosition, { // While warping, we might be hovering just above the ground. Don't want that to // trigger any falling behavior. - if(brain&&brain->fCallbackAction) + if(brain&&brain->fWalkingStrategy) { - brain->fCallbackAction->ResetAirTime(); + brain->fWalkingStrategy->ResetAirTime(); } // how far will we translate this frame? float thisDist = kFloatSpeed * elapsed; diff --git a/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvatarSDLModifier.cpp b/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvatarSDLModifier.cpp index d728b8fd..9f132f2a 100644 --- a/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvatarSDLModifier.cpp +++ b/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvatarSDLModifier.cpp @@ -47,7 +47,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com #include "../plAvatar/plAvBrainClimb.h" #include "../plAvatar/plAvBrainDrive.h" #include "../plAvatar/plAnimStage.h" -#include "../plAvatar/plAvCallbackAction.h" +#include "../plAvatar/plPhysicalControllerCore.h" #include "../pnSceneObject/plSceneObject.h" #include "../pnMessage/plSDLModifierMsg.h" #include "../plSDL/plSDL.h" diff --git a/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvatarTasks.cpp b/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvatarTasks.cpp index b3ed9ea6..cf67d229 100644 --- a/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvatarTasks.cpp +++ b/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvatarTasks.cpp @@ -53,7 +53,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com #include "plAGAnimInstance.h" #include "plAGModifier.h" #include "plMatrixChannel.h" -#include "plAvCallbackAction.h" +#include "plPhysicalControllerCore.h" #include "plAvatarMgr.h" // global @@ -689,7 +689,7 @@ hsBool plAvOneShotTask::Process(plArmatureMod *avatar, plArmatureBrain *brain, d if(fEnablePhysicsAtEnd) { #if 0//ndef PLASMA_EXTERNAL_RELEASE - if (!humanBrain || humanBrain->fCallbackAction->HitGroundInThisAge()) + if (!humanBrain || humanBrain->fWalkingStrategy->HitGroundInThisAge()) { // For some reason, calling CheckValidPosition at the beginning of // an age can cause detectors to incorrectly report collisions. So diff --git a/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plPhysicalControllerCore.cpp b/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plPhysicalControllerCore.cpp index 9dff5e3d..710645ff 100644 --- a/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plPhysicalControllerCore.cpp +++ b/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plPhysicalControllerCore.cpp @@ -40,548 +40,601 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com *==LICENSE==*/ #include "plPhysicalControllerCore.h" -#include "../plMessage/plLOSHitMsg.h" + +#include "plArmatureMod.h" +#include "plSwimRegion.h" +#include "plMatrixChannel.h" #include "../pnSceneObject/plCoordinateInterface.h" #include "../../NucleusLib/inc/plPhysical.h" #include "../../NucleusLib/pnMessage/plCorrectionMsg.h" -#include "plSwimRegion.h" -#include "plArmatureMod.h" // for LOS enum type -#include "plMatrixChannel.h" -#include "hsTimer.h" -#include "../plPhysx/plSimulationMgr.h" -#include "../plPhysx/plPXPhysical.h" -#include "../pnMessage/plSetNetGroupIDMsg.h" -#define kSWIMRADIUS 1.1f -#define kSWIMHEIGHT 2.8f -#define kGENERICCONTROLLERRADIUS 1.1f -#define kGENERICCONTROLLERHEIGHT 2.8f - -//#define kSWIMMINGCONTACTSLOPELIMIT (cosf(hsScalarDegToRad(80.f))) -const hsScalar plMovementStrategy::kAirTimeThreshold = .1f; // seconds + +// Gravity constants +#define kGravity -32.174f +#define kTerminalVelocity kGravity + +static inline hsVector3 GetYAxis(hsMatrix44 &mat) { return hsVector3(mat.fMap[1][0], mat.fMap[1][1], mat.fMap[1][2]); } +static float AngleRad2d(float x1, float y1, float x3, float y3); + bool CompareMatrices(const hsMatrix44 &matA, const hsMatrix44 &matB, float tolerance); -bool operator<(const plControllerSweepRecord left, const plControllerSweepRecord right) + + +// plPhysicalControllerCore +plPhysicalControllerCore::plPhysicalControllerCore(plKey OwnerSceneObject, hsScalar height, hsScalar radius) + : fOwner(OwnerSceneObject), + fWorldKey(nil), + fHeight(height), + fRadius(radius), + fLOSDB(plSimDefs::kLOSDBNone), + fMovementStrategy(nil), + fSimLength(0.0f), + fLocalRotation(0.0f, 0.0f, 0.0f, 1.0f), + fLocalPosition(0.0f, 0.0f, 0.0f), + fLastLocalPosition(0.0f, 0.0f, 0.0f), + fLinearVelocity(0.0f, 0.0f, 0.0f), + fAchievedLinearVelocity(0.0f, 0.0f, 0.0f), + fPushingPhysical(nil), + fFacingPushingPhysical(false), + fSeeking(false), + fEnabled(false), + fEnableChanged(false) +{ + fLastGlobalLoc.Reset(); + fPrevSubworldW2L.Reset(); +} + +const plCoordinateInterface* plPhysicalControllerCore::GetSubworldCI() { - if(left.TimeHit < right.TimeHit) return true; - else return false; + if (fWorldKey) + { + plSceneObject* so = plSceneObject::ConvertNoRef(fWorldKey->ObjectIsLoaded()); + if (so) + return so->GetCoordinateInterface(); + } + + return nil; } -plMovementStrategy::plMovementStrategy(plPhysicalControllerCore* core) + +void plPhysicalControllerCore::IncrementAngle(hsScalar deltaAngle) { - this->fTimeInAir=0.0f; - fCore=core; - fOwner=core->GetOwner(); - this->fPreferedControllerHeight=kGENERICCONTROLLERHEIGHT; - this->fPreferedControllerWidth=kGENERICCONTROLLERRADIUS; + hsVector3 axis; + hsScalar angle; + + fLocalRotation.NormalizeIfNeeded(); + fLocalRotation.GetAngleAxis(&angle, &axis); + if (axis.fZ < 0) + angle = (2.0f * hsScalarPI) - angle; // axis is backwards, so reverse the angle too + + angle += deltaAngle; + + // make sure we wrap around + if (angle < 0.0f) + angle = (2.0f * hsScalarPI) + angle; // angle is -, so this works like a subtract + if (angle >= (2.0f * hsScalarPI)) + angle = angle - (2.0f * hsScalarPI); + + // set the new angle + axis.Set(0.0f, 0.0f, 1.0f); + fLocalRotation.SetAngleAxis(angle, axis); } -void plMovementStrategy::IApplyKinematic() + +void plPhysicalControllerCore::IApply(hsScalar delSecs) { - // first apply sceneobject update to the kinematic + fSimLength = delSecs; + + // Match controller to owner if transform has changed since the last frame plSceneObject* so = plSceneObject::ConvertNoRef(fOwner->ObjectIsLoaded()); - if (so) + const hsMatrix44& l2w = so->GetCoordinateInterface()->GetLocalToWorld(); + if (!CompareMatrices(fLastGlobalLoc, l2w, 0.0001f)) + SetGlobalLoc(l2w); + + if (fEnabled) { - // If we've been moved since the last physics update (somebody warped us), - // update the physics before we apply velocity. - const hsMatrix44& l2w = so->GetCoordinateInterface()->GetLocalToWorld(); - if (!CompareMatrices(l2w, fCore->GetLastGlobalLoc(), .0001f)) + // Convert velocity from avatar to world space + if (!fLinearVelocity.IsEmpty()) { - fCore->SetKinematicLoc(l2w); - //fCore->SetGlobalLoc(l2w); + fLinearVelocity = l2w * fLinearVelocity; + + const plCoordinateInterface* subworldCI = GetSubworldCI(); + if (subworldCI) + fLinearVelocity = subworldCI->GetWorldToLocal() * fLinearVelocity; } + + fMovementStrategy->Apply(delSecs); } } -plPhysicalControllerCore::~plPhysicalControllerCore() +void plPhysicalControllerCore::IUpdate(int numSubSteps, hsScalar alpha) { + if (fEnabled) + { + // Update local position and acheived velocity + fLastLocalPosition = fLocalPosition; + GetPositionSim(fLocalPosition); + hsVector3 displacement = (hsVector3)(fLocalPosition - fLastLocalPosition); + fAchievedLinearVelocity = displacement / fSimLength; + + displacement /= (hsScalar)numSubSteps; + fLastLocalPosition = fLocalPosition - displacement; + hsPoint3 interpLocalPos = fLastLocalPosition + (displacement * alpha); + + // Update global location + fLocalRotation.MakeMatrix(&fLastGlobalLoc); + fLastGlobalLoc.SetTranslate(&interpLocalPos); + const plCoordinateInterface* subworldCI = GetSubworldCI(); + if (subworldCI) + { + const hsMatrix44& subL2W = subworldCI->GetLocalToWorld(); + fLastGlobalLoc = subL2W * fLastGlobalLoc; + fPrevSubworldW2L = subworldCI->GetWorldToLocal(); + } + + fMovementStrategy->Update(fSimLength); + ISendCorrectionMessages(true); + } + else + { + // Update global location if in a subworld + const plCoordinateInterface* subworldCI = GetSubworldCI(); + if (subworldCI) + { + hsMatrix44 l2s = fPrevSubworldW2L * fLastGlobalLoc; + const hsMatrix44& subL2W = subworldCI->GetLocalToWorld(); + fLastGlobalLoc = subL2W * l2s; + fPrevSubworldW2L = subworldCI->GetWorldToLocal(); + + ISendCorrectionMessages(); + } + } + + if (fEnableChanged) + IHandleEnableChanged(); } -void plPhysicalControllerCore::Apply(hsScalar delSecs) -{ - fSimLength=delSecs; - hsAssert(fMovementInterface, "plPhysicalControllerCore::Apply() missing a movement interface"); - if(fMovementInterface)fMovementInterface->Apply(delSecs); -} -void plPhysicalControllerCore::PostStep(hsScalar delSecs) -{ - hsAssert(fMovementInterface, "plPhysicalControllerCore::PostStep() missing a movement interface"); - if(fMovementInterface)fMovementInterface->PostStep(delSecs); -} -void plPhysicalControllerCore::Update(hsScalar delSecs) +void plPhysicalControllerCore::IUpdateNonPhysical(hsScalar alpha) { - hsAssert(fMovementInterface, "plPhysicalControllerCore::Update() missing a movement interface"); - if(fMovementInterface)fMovementInterface->Update(delSecs); - + // Update global location if owner transform hasn't changed. + plSceneObject* so = plSceneObject::ConvertNoRef(fOwner->ObjectIsLoaded()); + const hsMatrix44& l2w = so->GetCoordinateInterface()->GetLocalToWorld(); + if (CompareMatrices(fLastGlobalLoc, l2w, 0.0001f)) + { + hsVector3 displacement = (hsVector3)(fLocalPosition - fLastLocalPosition); + hsPoint3 interpLocalPos = fLastLocalPosition + (displacement * alpha); + + fLocalRotation.MakeMatrix(&fLastGlobalLoc); + fLastGlobalLoc.SetTranslate(&interpLocalPos); + const plCoordinateInterface* subworldCI = GetSubworldCI(); + if (subworldCI) + { + const hsMatrix44& subL2W = subworldCI->GetLocalToWorld(); + fLastGlobalLoc = subL2W * fLastGlobalLoc; + fPrevSubworldW2L = subworldCI->GetWorldToLocal(); + } + + ISendCorrectionMessages(); + } } -void plPhysicalControllerCore::SendCorrectionMessages() + +void plPhysicalControllerCore::ISendCorrectionMessages(bool dirtySynch) { - plSceneObject* so = plSceneObject::ConvertNoRef(fOwner->ObjectIsLoaded()); - plCorrectionMsg* corrMsg = TRACKED_NEW plCorrectionMsg; + plCorrectionMsg* corrMsg = TRACKED_NEW plCorrectionMsg(); corrMsg->fLocalToWorld = fLastGlobalLoc; corrMsg->fLocalToWorld.GetInverse(&corrMsg->fWorldToLocal); - corrMsg->fDirtySynch = true; - // Send the new position to the plArmatureMod and the scene object - const plArmatureMod* armMod = plArmatureMod::ConvertNoRef(so->GetModifierByType(plArmatureMod::Index())); - if (armMod) - corrMsg->AddReceiver(armMod->GetKey()); + corrMsg->fDirtySynch = dirtySynch; corrMsg->AddReceiver(fOwner); corrMsg->Send(); } -plPhysicalControllerCore::plPhysicalControllerCore(plKey OwnerSceneObject, hsScalar height, hsScalar radius) -:fMovementInterface(nil) -,fOwner(OwnerSceneObject) -,fHeight(height) -,fRadius(radius) -,fWorldKey(nil) -,fLinearVelocity(0.f,0.f,0.f) -,fAngularVelocity(0.f) -,fAchievedLinearVelocity(0.0f,0.0f,0.0f) -,fLocalPosition(0.0f,0.0f,0.0f) -,fLocalRotation(0.0f,0.0f,0.0f,1.0f) -,fSeeking(false) -,fEnabled(true) -,fEnableChanged(false) -,fLOSDB(plSimDefs::kLOSDBNone) -,fDisplacementThisStep(0.f,0.f,0.f) -,fSimLength(0.f) -,fKinematic(false) -,fKinematicEnableNextUpdate(false) -,fNeedsResize(false) -,fPushingPhysical(nil) + + +// Movement Strategy +plMovementStrategy::plMovementStrategy(plPhysicalControllerCore* controller) + : fController(controller) { } -void plPhysicalControllerCore::UpdateSubstepNonPhysical() -{ - // When we're in non-phys or a behavior we can't go through the rest of the function - // so we need to get out early, but we need to update the current position if we're - // in a subworld. - plSceneObject* so = plSceneObject::ConvertNoRef(fOwner->ObjectIsLoaded()); - const plCoordinateInterface* ci = GetSubworldCI(); - if (ci && so) - { - const hsMatrix44& soL2W = so->GetCoordinateInterface()->GetLocalToWorld(); - const hsMatrix44& ciL2W = ci->GetLocalToWorld(); - hsMatrix44 l2w =GetPrevSubworldW2L()* soL2W; - l2w = ciL2W * l2w; - hsMatrix44 w2l; - l2w.GetInverse(&w2l); - ((plCoordinateInterface*)so->GetCoordinateInterface())->SetTransform(l2w, w2l); - ((plCoordinateInterface*)so->GetCoordinateInterface())->FlushTransform(); - SetGlobalLoc(l2w); - } +void plMovementStrategy::Reset(bool newAge) { fController->SetMovementStrategy(this); } -} -void plPhysicalControllerCore::CheckAndHandleAnyStateChanges() -{ - if (IsEnabledChanged())HandleEnableChanged(); - if (IsKinematicChanged())HandleKinematicChanged(); - if (IsKinematicEnableNextUpdate())HandleKinematicEnableNextUpdate(); -} -void plPhysicalControllerCore::MoveActorToSim() +// Animated Movement Strategy +plAnimatedMovementStrategy::plAnimatedMovementStrategy(plAGApplicator* rootApp, plPhysicalControllerCore* controller) + : plMovementStrategy(controller), + fRootApp(rootApp), + fAnimLinearVel(0.0f, 0.0f, 0.0f), + fAnimAngularVel(0.0f), + fTurnStr(0.0f) { - // Get the current position of the physical - hsPoint3 curLocalPos; - hsPoint3 lastLocalPos; - GetPositionSim(curLocalPos); - MoveKinematicToController(curLocalPos); - lastLocalPos=GetLocalPosition(); - fDisplacementThisStep= hsVector3(curLocalPos - lastLocalPos); - fLocalPosition = curLocalPos; - if(fSimLength>0.0f) - fAchievedLinearVelocity=fDisplacementThisStep/fSimLength; - else fAchievedLinearVelocity.Set(0.0f,0.0f,0.0f); -} -void plPhysicalControllerCore::IncrementAngle(hsScalar deltaAngle) -{ - hsScalar angle; - hsVector3 axis; - fLocalRotation.NormalizeIfNeeded(); - fLocalRotation.GetAngleAxis(&angle, &axis); - // adjust it (quaternions are weird...) - if (axis.fZ < 0) - angle = (2*hsScalarPI) - angle; // axis is backwards, so reverse the angle too - angle += deltaAngle; - // make sure we wrap around - if (angle < 0) - angle = (2*hsScalarPI) + angle; // angle is -, so this works like a subtract - if (angle >= (2*hsScalarPI)) - angle = angle - (2*hsScalarPI); - // and set the new angle - fLocalRotation.SetAngleAxis(angle, hsVector3(0,0,1)); } -void plPhysicalControllerCore::UpdateWorldRelativePos() +void plAnimatedMovementStrategy::RecalcVelocity(double timeNow, hsScalar elapsed, hsBool useAnim) { + if (useAnim) + { + // while you may think it would be correct to cache this, what we're actually asking is "what would the animation's + // position be at the previous time given its *current* parameters (particularly blends)" + hsMatrix44 prevMat = ((plMatrixChannel *)fRootApp->GetChannel())->Value(timeNow - elapsed, true); + hsMatrix44 curMat = ((plMatrixChannel *)fRootApp->GetChannel())->Value(timeNow, true); - // Apply rotation and translation - fLocalRotation.MakeMatrix(&fLastGlobalLoc); - fLastGlobalLoc.SetTranslate(&fLocalPosition); - // Localize to global coords if in a subworld - const plCoordinateInterface* ci = GetSubworldCI(); - if (ci) + IRecalcLinearVelocity(elapsed, prevMat, curMat); + IRecalcAngularVelocity(elapsed, prevMat, curMat); + + // Update controller rotation + hsScalar zRot = fAnimAngularVel + fTurnStr; + if (hsABS(zRot) > 0.0001f) + fController->IncrementAngle(zRot * elapsed); + } + else { - const hsMatrix44& l2w = ci->GetLocalToWorld(); - fLastGlobalLoc = l2w * fLastGlobalLoc; + fAnimLinearVel.Set(0.0f, 0.0f, 0.0f); + fAnimAngularVel = 0.0f; } + + // Update controller velocity + fController->SetLinearVelocity(fAnimLinearVel); } -plPhysical* plPhysicalControllerCore::GetPushingPhysical() + +void plAnimatedMovementStrategy::IRecalcLinearVelocity(float elapsed, hsMatrix44 &prevMat, hsMatrix44 &curMat) { - return fPushingPhysical; + hsPoint3 startPos(0.0f, 0.0f, 0.0f); // default position (at start of anim) + hsPoint3 prevPos = prevMat.GetTranslate(); // position previous frame + hsPoint3 nowPos = curMat.GetTranslate(); // position current frame + + hsVector3 prev2Now = (hsVector3)(nowPos - prevPos); // frame-to-frame delta + + if (fabs(prev2Now.fX) < 0.0001f && fabs(prev2Now.fY) < 0.0001f && fabs(prev2Now.fZ) < 0.0001f) + { + fAnimLinearVel.Set(0.f, 0.f, 0.f); + } + else + { + hsVector3 start2Now = (hsVector3)(nowPos - startPos); // start-to-frame delta + + float prev2NowMagSqr = prev2Now.MagnitudeSquared(); + float start2NowMagSqr = start2Now.MagnitudeSquared(); + + float dot = prev2Now.InnerProduct(start2Now); + + // HANDLING ANIMATION WRAPPING: + // the vector from the animation origin to the current frame should point in roughly + // the same direction as the vector from the previous animation position to the + // current animation position. + // + // If they don't agree (dot < 0,) then we probably mpst wrapped around. + // The right answer would be to compare the current frame to the start of + // the anim loop, but it's cheaper to cheat and use the previous frame's velocity. + if (dot > 0.0f) + { + prev2Now /= elapsed; + + float xfabs = fabs(prev2Now.fX); + float yfabs = fabs(prev2Now.fY); + float zfabs = fabs(prev2Now.fZ); + static const float maxVel = 20.0f; + hsBool valid = xfabs < maxVel && yfabs < maxVel && zfabs < maxVel; + + if (valid) + { + fAnimLinearVel = prev2Now; + } + } + } } -const hsVector3& plPhysicalControllerCore::GetLinearVelocity() + +void plAnimatedMovementStrategy::IRecalcAngularVelocity(float elapsed, hsMatrix44 &prevMat, hsMatrix44 &curMat) { - return fLinearVelocity; + fAnimAngularVel = 0.0f; + hsScalar appliedVelocity = 0.0f; + hsVector3 prevForward = GetYAxis(prevMat); + hsVector3 curForward = GetYAxis(curMat); + + hsScalar angleSincePrev = AngleRad2d(curForward.fX, curForward.fY, prevForward.fX, prevForward.fY); + hsBool sincePrevSign = angleSincePrev > 0.0f; + if (angleSincePrev > hsScalarPI) + angleSincePrev = angleSincePrev - TWO_PI; + + const hsVector3 startForward = hsVector3(0.0f, -1.0f, 0.0f); // the Y orientation of a "resting" armature.... + hsScalar angleSinceStart = AngleRad2d(curForward.fX, curForward.fY, startForward.fX, startForward.fY); + hsBool sinceStartSign = angleSinceStart > 0.0f; + if (angleSinceStart > hsScalarPI) + angleSinceStart = angleSinceStart - TWO_PI; + + // HANDLING ANIMATION WRAPPING: + // under normal conditions, the angle from rest to the current frame will have the same + // sign as the angle from the previous frame to the current frame. + // if it does not, we have (most likely) wrapped the motivating animation from frame n back + // to frame zero, creating a large angle from the previous frame to the current one + if (sincePrevSign == sinceStartSign) + { + // signs are the same; didn't wrap; use the frame-to-frame angle difference + appliedVelocity = angleSincePrev / elapsed; // rotation / time + if (fabs(appliedVelocity) < 3) + { + fAnimAngularVel = appliedVelocity; + } + } } -bool plPhysicalControllerCore::GetFacingPushingPhysical() + + +// Walking Strategy +plWalkingStrategy::plWalkingStrategy(plAGApplicator* rootApp, plPhysicalControllerCore* controller) + : plAnimatedMovementStrategy(rootApp, controller), + fSlidingNormals(), + fImpactVelocity(0.0f, 0.0f, 0.0f), + fImpactTime(0.0f), + fTimeInAir(0.0f), + fControlledFlightTime(0.0f), + fControlledFlight(0), + fGroundHit(false), + fFalseGround(false), + fHeadHit(false), + fClearImpact(false), + fHitGroundInThisAge(false) { - return fFacingPushingPhysical; } -/////////////////////////// -//Walking Strategy + void plWalkingStrategy::Apply(hsScalar delSecs) { - //Apply Should Only be Called from a PhysicalControllerCore - hsAssert(fCore,"No Core shouldn't be Applying"); - UInt32 collideFlags = - 1<IsSeeking()) + hsVector3 velocity = fController->GetLinearVelocity(); + hsVector3 achievedVelocity = fController->GetAchievedLinearVelocity(); + + // Add in gravity if the avatar's z velocity isn't being set explicitly + if (hsABS(velocity.fZ) < 0.001f) { - collideFlags|=(1<GetLinearVelocity(); - hsVector3 AchievedLinearVelocity=fCore->GetAchievedLinearVelocity(); - hsPoint3 positionBegin; - fCore->GetPositionSim(positionBegin); - bool recovered=false; - if (fCore->IsKinematic()) + + // If we're airborne and the velocity isn't set, use the velocity from + // the last frame so we maintain momentum. + if (!IsOnGround() && velocity.fX == 0.0f && velocity.fY == 0.0f) { - plSceneObject* so = plSceneObject::ConvertNoRef(fOwner->ObjectIsLoaded()); - if (so) - { - // If we've been moved since the last physics update (somebody warped us), - // update the physics before we apply velocity. - const hsMatrix44& l2w = so->GetCoordinateInterface()->GetLocalToWorld(); - if (!CompareMatrices(l2w, fCore->GetLastGlobalLoc(), .0001f)) - { - fCore->SetKinematicLoc(l2w); - fCore->SetGlobalLoc(l2w); - } - } - return; + velocity.fX = achievedVelocity.fX; + velocity.fY = achievedVelocity.fY; } - if (!fCore->IsEnabled()) - return; - - bool gotGroundHit = fGroundHit; - fGroundHit = false; - - fCore->SetPushingPhysical(nil); - fCore->SetFacingPushingPhysical( false); - plSceneObject* so = plSceneObject::ConvertNoRef(fOwner->ObjectIsLoaded()); - if (so) + if (!fGroundHit && fSlidingNormals.Count()) { - static const float kGravity = -32.f; - // If we've been moved since the last physics update (somebody warped us), - // update the physics before we apply velocity. - const hsMatrix44& l2w = so->GetCoordinateInterface()->GetLocalToWorld(); - if (!CompareMatrices(l2w, fCore->GetLastGlobalLoc(), .0001f)) - fCore->SetGlobalLoc(l2w); - - // Convert our avatar relative velocity to subworld relative - if (!LinearVelocity.IsEmpty()) + // We're not on solid ground, so we should be sliding against whatever + // we're hitting (like a rock cliff). Each vector in fSlidingNormals is + // the surface normal of a collision that's too steep to be ground, so + // we project our current velocity onto that plane and slide along the + // wall. + // + // Also, sometimes PhysX reports a bunch of collisions from the wall, + // but nothing from underneath (when there should be). So if we're not + // touching ground, we offset the avatar in the direction of the + // surface normal(s). This doesn't fix the issue 100%, but it's a hell + // of a lot better than nothing, and suitable duct tape until a future + // PhysX revision fixes the issue. + // + // Yes, there's room for optimization here if we care. + hsVector3 offset(0.0f, 0.0f, 0.0f); + for (int i = 0; i < fSlidingNormals.GetCount(); i++) { - LinearVelocity = l2w * LinearVelocity; - const plCoordinateInterface* subworldCI = fCore->GetSubworldCI(); - if (subworldCI) - LinearVelocity = subworldCI->GetWorldToLocal() * LinearVelocity; - } + offset += fSlidingNormals[i]; + hsVector3 velNorm = velocity; - // Add in gravity if the avatar's z velocity isn't being set explicitly - // (Add in a little fudge factor, since the animations usually add a - // tiny bit of z.) - if (hsABS(LinearVelocity.fZ) < 0.001f) - { - // Get our previous z velocity. If we're on the ground, clamp it to zero at - // the largest, so we won't launch into the air if we're running uphill. - hsScalar prevZVel = AchievedLinearVelocity.fZ; - if (IsOnGround()) - prevZVel = hsMinimum(prevZVel, 0.f); - hsScalar grav = kGravity * delSecs; - // If our gravity contribution isn't high enough this frame, we won't - // report a collision even when standing on solid ground. - hsScalar maxGrav = -.001f / delSecs; - if (grav > maxGrav) - grav = maxGrav; - LinearVelocity.fZ = prevZVel + grav; - } + if (velNorm.MagnitudeSquared() > 0.0f) + velNorm.Normalize(); - // If we're airborne and the velocity isn't set, use the velocity from - // the last frame so we maintain momentum. - if (!IsOnGround() && LinearVelocity.fX == 0.f && LinearVelocity.fY == 0.f) - { - LinearVelocity.fX = AchievedLinearVelocity.fX; - LinearVelocity.fY = AchievedLinearVelocity.fY; - } - if (!IsOnGround() || IsOnFalseGround()) - { - // We're not on solid ground, so we should be sliding against whatever - // we're hitting (like a rock cliff). Each vector in fSlidingNormals is - // the surface normal of a collision that's too steep to be ground, so - // we project our current velocity onto that plane and slide along the - // wall. - // - // Also, sometimes PhysX reports a bunch of collisions from the wall, - // but nothing from underneath (when there should be). So if we're not - // touching ground, we offset the avatar in the direction of the - // surface normal(s). This doesn't fix the issue 100%, but it's a hell - // of a lot better than nothing, and suitable duct tape until a future - // PhysX revision fixes the issue. - // - // Yes, there's room for optimization here if we care. - hsVector3 offset(0.f, 0.f, 0.f); - for (int i = 0; i < fContactNormals.GetCount(); i++) + if (velNorm * fSlidingNormals[i] < 0.0f) { - offset += fContactNormals[i]; - hsVector3 velNorm = LinearVelocity; - - if (velNorm.MagnitudeSquared() > 0) - velNorm.Normalize(); - - if (velNorm * fContactNormals[i] < 0) - { - hsVector3 proj = (velNorm % fContactNormals[i]) % fContactNormals[i]; - if (velNorm * proj < 0) - proj *= -1.f; - LinearVelocity = LinearVelocity.Magnitude() * proj; - } - } - if (offset.MagnitudeSquared() > 0) - { - // 5 ft/sec is roughly the speed we walk backwards. - // The higher the value, the less likely you'll trip - // the bug, and this seems reasonable. - offset.Normalize(); - LinearVelocity += offset * 5.0f; - } - } - //make terminal velocity equal to k. it is wrong but has been this way and - //don't want to break any puzzles. on top of that it will reduce tunneling behavior - if(LinearVelocity.fZSetLinearVelocity(LinearVelocity); - // Scale the velocity to our actual step size (by default it's feet/sec) - hsVector3 vel(LinearVelocity.fX * delSecs, LinearVelocity.fY * delSecs, LinearVelocity.fZ * delSecs); - unsigned int colFlags = 0; - fGroundHit = false; - fFalseGround = false; - fContactNormals.Swap(fPrevSlidingNormals); - fContactNormals.SetCount(0); - fCore->Move(vel, collideFlags, colFlags); - ICheckForFalseGround(); - //if(fReqMove2) fCore->Move2(vel); - /*If the Physx controller thinks we have a collision from below, need to make sure we - have at least have false ground, otherwise Autostepping can send us into the air, and we will some times - float/panic link. For some reason the NxControllerHitReport does not always send messages - regarding Controller contact with ground plane, but will (almost) always return NXCC_COLLISION_DOWN - with the move method. - */ - if((colFlags&kBottom ) &&(fGroundHit==false)) - { - fFalseGround=true; + velocity = velocity.Magnitude() * proj; + } } - - if(colFlags&kTop) + if (offset.MagnitudeSquared() > 0.0f) { - fHitHead=true; - //Did you hit your head on a dynamic? - //with Physx's wonderful controller hit report vs flags issues we need to actually sweep to see - std::multiset< plControllerSweepRecord > HitsDynamic; - UInt32 testFlag=1<GetPositionSim(startPos); - endPos= startPos + vel; - int NumObjsHit=fCore->SweepControllerPath(startPos, endPos, true, false, testFlag, HitsDynamic); - if(NumObjsHit>0) - { - for(std::multiset< plControllerSweepRecord >::iterator curObj= HitsDynamic.begin(); - curObj!=HitsDynamic.end(); curObj++) - { - - hsAssert(curObj->ObjHit,"We allegedly hit something, but there is no plasma physical associated with it"); - if(curObj->ObjHit) - {//really we shouldn't have to check hitObj should be nil only if we miss, or the physX object - //doesn't have a user data associated with this either way this just shouldn't happen - hsVector3 hitObjVel; - curObj->ObjHit->GetLinearVelocitySim(hitObjVel); - hsVector3 relativevel=LinearVelocity-hitObjVel; - curObj->ObjHit->SetHitForce(relativevel * 10.0f * (*curObj).ObjHit->GetMass(), (*curObj).locHit); - } - } - HitsDynamic.clear(); - } + // 5 ft/sec is roughly the speed we walk backwards. + // The higher the value, the less likely you'll trip + // the bug, and this seems reasonable. + offset.Normalize(); + velocity += offset * 5.0f; } } + + if (velocity.fZ < kTerminalVelocity) + velocity.fZ = kTerminalVelocity; + + // Convert to a displacement vector + hsVector3 displacement = velocity * delSecs; + + // Reset vars and move the controller + fController->SetPushingPhysical(nil); + fController->SetFacingPushingPhysical(false); + fGroundHit = fFalseGround = fHeadHit = false; + fSlidingNormals.SetCount(0); + + unsigned int collideResults = 0; + unsigned int collideFlags = 1<IsSeeking()) + collideFlags |= (1<Move(displacement, collideFlags, collideResults); + + if ((!fGroundHit) && (collideResults & kBottom)) + fFalseGround = true; + + if (collideResults & kTop) + fHeadHit = true; } -void plWalkingStrategy::ICheckForFalseGround() +void plWalkingStrategy::Update(hsScalar delSecs) { - if (fGroundHit) - return; // Already collided with "real" ground. - - // We need to check for the case where the avatar hasn't collided with "ground", but is colliding - // with a few other objects so that he's not actually falling (wedged in between some slopes). - // We do this by answering the following question (in 2d top-down space): "If you sort the contact - // normals by angle, is there a large enough gap between normals?" - // - // If you think in terms of geometry, this means a collection of surfaces are all pushing on you. - // If they're pushing from all sides, you have nowhere to go, and you won't fall. There needs to be - // a gap, so that you're pushed out and have somewhere to fall. This is the same as finding a gap - // larger than 180 degrees between sorted normals. - // - // The problem is that on top of that, the avatar needs enough force to shove him out that gap (he - // has to overcome friction). I deal with that by making the threshold (360 - (180 - 60) = 240). I've - // seen up to 220 reached in actual gameplay in a situation where we'd want this to take effect. - // This is the same running into 2 walls where the angle between them is 60. - int i, j; - const hsScalar threshold = hsScalarDegToRad(240.f); - int numContacts = fContactNormals.GetCount() + fPrevSlidingNormals.GetCount(); - if (numContacts >= 2) + if (fGroundHit || fFalseGround) + fTimeInAir = 0.0f; + else { - // For extra fun... PhysX will actually report some collisions every other frame, as though - // we're bouncing back and forth between the two (or more) objects blocking us. So it's not - // enough to look at this frame's collisions, we have to check previous frames too. - hsTArray fCollisionAngles; - fCollisionAngles.SetCount(numContacts); - int angleIdx = 0; - for (i = 0; i < fContactNormals.GetCount(); i++, angleIdx++) - { - fCollisionAngles[angleIdx] = hsATan2(fContactNormals[i].fY, fContactNormals[i].fX); - } - for (i = 0; i < fPrevSlidingNormals.GetCount(); i++, angleIdx++) - { - fCollisionAngles[angleIdx] = hsATan2(fPrevSlidingNormals[i].fY, fPrevSlidingNormals[i].fX); - } - // numContacts is rarely larger than 6, so let's do a simple bubble sort. - for (i = 0; i < numContacts; i++) - { - for (j = i + 1; j < numContacts; j++) - { - if (fCollisionAngles[i] > fCollisionAngles[j]) - { - hsScalar tempAngle = fCollisionAngles[i]; - fCollisionAngles[i] = fCollisionAngles[j]; - fCollisionAngles[j] = tempAngle; - } - } - } - // sorted, now we check. - for (i = 1; i < numContacts; i++) - { - if (fCollisionAngles[i] - fCollisionAngles[i - 1] >= threshold) - break; - } - if (i == numContacts) - { - // We got to the end. Check the last with the first and make your decision. - if (!(fCollisionAngles[0] - fCollisionAngles[numContacts - 1] >= (threshold - 2 * hsScalarPI))) - fFalseGround = true; + fTimeInAir += delSecs; + if (fHeadHit) + { + // If we're airborne and hit our head, override achieved velocity to avoid being shoved sideways + hsVector3 velocity = fController->GetLinearVelocity(); + hsVector3 achievedVelocity = fController->GetAchievedLinearVelocity(); + + achievedVelocity.fX = velocity.fX; + achievedVelocity.fY = velocity.fY; + if (achievedVelocity.fZ > 0.0f) + achievedVelocity.fZ = 0.0f; + + fController->OverrideAchievedLinearVelocity(achievedVelocity); } } + + if (!fHitGroundInThisAge && IsOnGround()) + fHitGroundInThisAge = true; + + if (fClearImpact) + { + fImpactTime = 0.0f; + fImpactVelocity.Set(0.0f, 0.0f, 0.0f); + } + + if (IsOnGround()) + fClearImpact = true; + else + { + fImpactTime = fTimeInAir; + fImpactVelocity = fController->GetAchievedLinearVelocity(); + // convert orientation from subworld to avatar-local coordinates + fImpactVelocity = (hsVector3)fController->GetLocalRotation().Rotate(&fImpactVelocity); + fClearImpact = false; + } + + if (fControlledFlight != 0) + { + if (IsOnGround()) + fControlledFlightTime = fTimeInAir; + + if (fControlledFlightTime > kControlledFlightThreshold) + EnableControlledFlight(false); + } } -void plWalkingStrategy::Update(hsScalar delSecs) + +void plWalkingStrategy::AddContactNormals(hsVector3& vec) { - //Update Should Only be Called from a PhysicalControllerCore - hsAssert(fCore,"Running Update: but have no Core"); - hsScalar AngularVelocity=fCore->GetAngularVelocity(); - hsVector3 LinearVelocity=fCore->GetLinearVelocity(); + hsScalar dot = vec * kAvatarUp; + if (dot >= 0.5f) + fGroundHit = true; + else + fSlidingNormals.Append(vec); +} - if (!fCore->IsEnabled() || fCore->IsKinematic()) +void plWalkingStrategy::Reset(bool newAge) +{ + plMovementStrategy::Reset(newAge); + if (newAge) { - fCore->UpdateSubstepNonPhysical(); - return; + fTimeInAir = 0.0f; + fClearImpact = true; + fHitGroundInThisAge = false; + fSlidingNormals.SetCount(0); } - fCore->CheckAndHandleAnyStateChanges(); - if (!fGroundHit && !fFalseGround) - fTimeInAir += delSecs; - else - fTimeInAir = 0.f; - plSceneObject* so = plSceneObject::ConvertNoRef(fOwner->ObjectIsLoaded()); - if (so) +} + +bool plWalkingStrategy::EnableControlledFlight(bool status) +{ + if (status) { - fCore->MoveActorToSim(); - if (AngularVelocity != 0.f) - { - hsScalar deltaAngle=AngularVelocity*delSecs; - fCore->IncrementAngle( deltaAngle); - } - // We can't only send updates when the physical position changes because the - // world relative position may be changing all the time if we're in a subworld. - fCore->UpdateWorldRelativePos(); - fCore->SendCorrectionMessages(); - bool headhit=fHitHead; - fHitHead=false; - hsVector3 AchievedLinearVelocity; - AchievedLinearVelocity = fCore->DisplacementLastStep(); - AchievedLinearVelocity=AchievedLinearVelocity/delSecs; - - /*if we hit our head the sweep api might try to - move us laterally to go as high as we requested kind of like autostep, to top it off the - way the NxCharacter and the sweep api work as a whole NxControllerHitReport::OnShapeHit - wont be called regarding the head blow. - if we are airborne: with out this we will gain large amounts of velocity in the x y plane - and on account of fAchievedLinearVelocity being used in the next step we will fly sideways - */ - if(headhit&&!(fGroundHit||fFalseGround)) - { - //we have hit our head and we don't have anything beneath our feet - //not really friction just a way to make it seem more realistic keep between 0 and 1 - hsScalar headFriction=0.0f; - AchievedLinearVelocity.fX=(1.0f-headFriction)*LinearVelocity.fX; - AchievedLinearVelocity.fY=(1.0f-headFriction)*LinearVelocity.fY; - //only clamping when hitting head and going upwards, if going down leave it be - // this should only occur when going down stairwells with low ceilings like in cleft - //kitchen area - if(AchievedLinearVelocity.fZ>0.0f) - { - AchievedLinearVelocity.fZ=0.0f; - } - fCore->OverrideAchievedVelocity(AchievedLinearVelocity); - } - fCore->OverrideAchievedVelocity(AchievedLinearVelocity); - // Apply angular velocity + if (fControlledFlight == 0) + fControlledFlightTime = 0.0f; + + ++fControlledFlight; } + else + fControlledFlight = __max(--fControlledFlight, 0); + + return status; +} + +plPhysical* plWalkingStrategy::GetPushingPhysical() const { return fController->GetPushingPhysical(); } +bool plWalkingStrategy::GetFacingPushingPhysical() const { return fController->GetFacingPushingPhysical(); } + +const hsScalar plWalkingStrategy::kAirTimeThreshold = 0.1f; +const hsScalar plWalkingStrategy::kControlledFlightThreshold = 1.0f; - LinearVelocity.Set(0.f, 0.f, 0.f); - AngularVelocity = 0.f; - fCore->SetVelocities(LinearVelocity,AngularVelocity); +// Swim Strategy +plSwimStrategy::plSwimStrategy(plAGApplicator* rootApp, plPhysicalControllerCore* controller) + : plAnimatedMovementStrategy(rootApp, controller), + fBuoyancy(0.0f), + fSurfaceHeight(0.0f), + fCurrentRegion(nil), + fOnGround(false), + fHadContacts(false) +{ } +void plSwimStrategy::Apply(hsScalar delSecs) +{ + hsVector3 velocity = fController->GetLinearVelocity(); + hsVector3 achievedVelocity = fController->GetAchievedLinearVelocity(); + + IAdjustBuoyancy(); + + //trying to dampen the oscillations + hsScalar retardent = 0.0f; + static hsScalar finalBobSpeed = 0.5f; + if ((achievedVelocity.fZ > finalBobSpeed) || (achievedVelocity.fZ < -finalBobSpeed)) + retardent = achievedVelocity.fZ * -0.90f; + + hsScalar zacc = (1.0f - fBuoyancy) * kGravity + retardent; + velocity.fZ += (zacc * delSecs); + + velocity.fZ += achievedVelocity.fZ; + + // Water Current + if (fCurrentRegion != nil) + { + hsScalar angCurrent = 0.0f; + hsVector3 linCurrent(0.0f, 0.0f, 0.0f); + fCurrentRegion->GetCurrent(fController, linCurrent, angCurrent, delSecs); + + if (hsABS(angCurrent) > 0.0001f) + fController->IncrementAngle(angCurrent * delSecs); + + velocity += linCurrent; -void plWalkingStrategy::IAddContactNormals(hsVector3& vec) -{ - //TODO: ADD in functionality to Adjust walkable slope for controller, also apply that in here + if (velocity.fZ > fCurrentRegion->fMaxUpwardVel) + velocity.fZ = fCurrentRegion->fMaxUpwardVel; + } + + if (velocity.fZ < kTerminalVelocity) + velocity.fZ = kTerminalVelocity; + + // Convert to displacement vector + hsVector3 displacement = velocity * delSecs; + + // Reset vars and move controller // + fController->SetPushingPhysical(nil); + fController->SetFacingPushingPhysical(false); + fHadContacts = fOnGround = false; + + unsigned int collideResults = 0; + unsigned int collideFlags = 1<IsSeeking()) + collideFlags |= (1<Move(displacement, collideFlags, collideResults); + + if ((collideResults & kBottom) || (collideResults & kSides)) + fHadContacts = true; +} + +void plSwimStrategy::AddContactNormals(hsVector3& vec) +{ hsScalar dot = vec * kAvatarUp; - if ( dot >= kSLOPELIMIT ) fGroundHit=true; - else plMovementStrategySimulationInterface::IAddContactNormals(vec); + if (dot >= kSlopeLimit) + fOnGround = true; } -//swimming strategy -plSwimStrategy::plSwimStrategy(plPhysicalControllerCore* core) - :plMovementStrategy(core) - ,fOnGround(false) - ,fHadContacts(false) - ,fBuoyancy(0.f) - ,fSurfaceHeight(0.0f) - ,fCurrentRegion(nil) +void plSwimStrategy::SetSurface(plSwimRegionInterface *region, hsScalar surfaceHeight) { - fPreferedControllerHeight=kSWIMHEIGHT; - fPreferedControllerWidth=kSWIMRADIUS; - fCore->SetMovementSimulationInterface(this); + fCurrentRegion = region; + fSurfaceHeight = surfaceHeight; } void plSwimStrategy::IAdjustBuoyancy() { @@ -599,383 +652,148 @@ void plSwimStrategy::IAdjustBuoyancy() return; } - hsMatrix44 l2w, w2l; hsPoint3 posSim; - fCore->GetPositionSim(posSim); - float depth = fSurfaceHeight - posSim.fZ; - //this isn't a smooth transition but hopefully it won't be too obvious - if(depth<=0.0)//all the away above water + fController->GetPositionSim(posSim); + float depth = fSurfaceHeight - posSim.fZ; + + // this isn't a smooth transition but hopefully it won't be too obvious + if (depth <= 0.0) //all the away above water fBuoyancy = 0.f; // Same as being above ground. Plain old gravity. - else if(depth >= 5.0f) fBuoyancy=3.0f;//completely Submereged - else fBuoyancy =(depth/surfaceDepth ); - + else if (depth >= 5.0f) + fBuoyancy = 3.0f; //completely Submereged + else + fBuoyancy = depth / surfaceDepth; } -void plSwimStrategy::Apply(hsScalar delSecs) -{ - hsAssert(fCore,"PlSwimStrategy::Apply No Core shouldn't be Applying"); - UInt32 collideFlags = - 1<IsSeeking()) - { - collideFlags|=(1<GetLinearVelocity(); - hsVector3 AchievedLinearVelocity=fCore->GetAchievedLinearVelocity(); - if (fCore->IsKinematic()) - { - plSceneObject* so = plSceneObject::ConvertNoRef(fOwner->ObjectIsLoaded()); - if (so) - { - // If we've been moved since the last physics update (somebody warped us), - // update the physics before we apply velocity. - const hsMatrix44& l2w = so->GetCoordinateInterface()->GetLocalToWorld(); - if (!CompareMatrices(l2w, fCore->GetLastGlobalLoc(), .0001f)) - { - fCore->SetKinematicLoc(l2w); - fCore->SetGlobalLoc(l2w); - } - } - return; - - } - if (!fCore->IsEnabled()) - return; - - fCore->SetPushingPhysical(nil); - fCore->SetFacingPushingPhysical( false); - fHadContacts=false; - fOnGround=false; - plSceneObject* so = plSceneObject::ConvertNoRef(fOwner->ObjectIsLoaded()); - if (so) - { - // If we've been moved since the last physics update (somebody warped us), - // update the physics before we apply velocity. - const hsMatrix44& l2w = so->GetCoordinateInterface()->GetLocalToWorld(); - if (!CompareMatrices(l2w, fCore->GetLastGlobalLoc(), .0001f)) - fCore->SetGlobalLoc(l2w); - - // Convert our avatar relative velocity to subworld relative - if (!LinearVelocity.IsEmpty()) - { - LinearVelocity = l2w * LinearVelocity; - const plCoordinateInterface* subworldCI = fCore->GetSubworldCI(); - if (subworldCI) - LinearVelocity = subworldCI->GetWorldToLocal() * LinearVelocity; - } - IAdjustBuoyancy(); - hsScalar zacc; - hsScalar retardent=0.0f; - static hsScalar FinalBobSpeed=0.5f; - //trying to dampen the oscillations - if((AchievedLinearVelocity.fZ>FinalBobSpeed)||(AchievedLinearVelocity.fZ<-FinalBobSpeed)) - retardent=AchievedLinearVelocity.fZ *-.90f; - zacc=(1-fBuoyancy)*-32.f + retardent; - - hsVector3 linCurrent(0.0f,0.0f,0.0f); - hsScalar angCurrent = 0.f; - if (fCurrentRegion != nil) - { - - fCurrentRegion->GetCurrent(fCore, linCurrent, angCurrent, delSecs); - //fAngularVelocity+= angCurrent; - } - hsVector3 vel(LinearVelocity.fX , LinearVelocity.fY , AchievedLinearVelocity.fZ+ LinearVelocity.fZ ); - vel.fZ= vel.fZ + zacc*delSecs; - if(fCurrentRegion!=nil){ - if (vel.fZ > fCurrentRegion->fMaxUpwardVel) - { - vel.fZ = fCurrentRegion->fMaxUpwardVel; - } - vel+= linCurrent; - } - static const float kGravity = -32.f; - if(vel.fZMove(displacement,collideFlags,colFlags); - if((colFlags&kBottom)||(colFlags&kSides))fHadContacts=true; - hsScalar angvel=fCore->GetAngularVelocity(); - fCore->SetAngularVelocity(angvel +angCurrent); - } + +// Dynamic Walking Strategy +plDynamicWalkingStrategy::plDynamicWalkingStrategy(plAGApplicator* rootApp, plPhysicalControllerCore* controller) + : plWalkingStrategy(rootApp, controller) +{ } -void plSwimStrategy::Update(hsScalar delSecs) + +void plDynamicWalkingStrategy::Apply(hsScalar delSecs) { - hsAssert(fCore,"Running Update: but have no Core"); - hsScalar AngularVelocity=fCore->GetAngularVelocity(); - hsVector3 LinearVelocity=fCore->GetLinearVelocity(); - if (!fCore->IsEnabled() || fCore->IsKinematic()) - { - fCore->UpdateSubstepNonPhysical(); - return; - } - fCore->CheckAndHandleAnyStateChanges(); - plSceneObject* so = plSceneObject::ConvertNoRef(fOwner->ObjectIsLoaded()); - if (so) - { - fCore->MoveActorToSim(); + hsVector3 velocity = fController->GetLinearVelocity(); + hsVector3 achievedVelocity = fController->GetAchievedLinearVelocity(); - if (AngularVelocity != 0.f) - { - hsScalar deltaAngle=AngularVelocity*delSecs; - fCore->IncrementAngle( deltaAngle); - } - fCore->UpdateWorldRelativePos(); - fCore->SendCorrectionMessages(); - } - LinearVelocity.Set(0.f, 0.f, 0.f); - AngularVelocity = 0.f; - fCore->SetVelocities(LinearVelocity,AngularVelocity); -} -void plSwimStrategy::IAddContactNormals(hsVector3& vec) -{ - //TODO: ADD in functionality to Adjust walkable slope for controller, also apply that in here - hsScalar dot = vec * kAvatarUp; - if ( dot >= kSLOPELIMIT ) + // Add in gravity if the avatar's z velocity isn't being set explicitly + if (hsABS(velocity.fZ) < 0.001f) { - fOnGround=true; - // fHadContacts=true; + // Get our previous z velocity. If we're on the ground, clamp it to zero at + // the largest, so we won't launch into the air if we're running uphill. + hsScalar prevZVel = achievedVelocity.fZ; + if (IsOnGround()) + prevZVel = hsMinimum(prevZVel, 0.f); + + velocity.fZ = prevZVel + (kGravity * delSecs); } - else plMovementStrategySimulationInterface::IAddContactNormals(vec); -} -void plSwimStrategy::SetSurface(plSwimRegionInterface *region, hsScalar surfaceHeight) -{ - fCurrentRegion=region; - fSurfaceHeight=surfaceHeight; + + if (velocity.fZ < kTerminalVelocity) + velocity.fZ = kTerminalVelocity; + + fController->SetPushingPhysical(nil); + fController->SetFacingPushingPhysical(false); + fGroundHit = fFalseGround = false; + + hsScalar groundZVelocity; + if (ICheckForGround(groundZVelocity)) + velocity.fZ += groundZVelocity; + + fController->SetLinearVelocitySim(velocity); } -void plRidingAnimatedPhysicalStrategy::Apply(hsScalar delSecs) + +bool plDynamicWalkingStrategy::ICheckForGround(hsScalar& zVelocity) { - hsVector3 LinearVelocity=fCore->GetLinearVelocity(); - hsVector3 AchievedLinearVelocity=fCore->GetAchievedLinearVelocity(); - if (fCore->IsKinematic()) - { - //want to make sure nothing funky happens in the sim - IApplyKinematic(); - return; - } - if (!fCore->IsEnabled()) - return; + std::vector groundHits; + UInt32 collideFlags = 1<GetPositionSim(startPos); + hsPoint3 endPos = startPos; - - fCore->SetPushingPhysical(nil); - fCore->SetFacingPushingPhysical( false); - plSceneObject* so = plSceneObject::ConvertNoRef(fOwner->ObjectIsLoaded()); - hsPoint3 startPos, desiredDestination, endPos; - fCore->GetPositionSim(startPos); - UInt32 collideFlags = - 1< GroundHitRecords; - int possiblePlatformCount =fCore->SweepControllerPath(startPos, startPos + hsPoint3(0.f,0.f, -0.002f), true, true, collideFlags, GroundHitRecords); - float maxPlatformVel = - FLT_MAX; - int platformCount=0; - fGroundHit = false; - if(possiblePlatformCount) + // Set sweep length + startPos.fZ += 0.05f; + endPos.fZ -= 0.05f; + + int possiblePlatformCount = fController->SweepControllerPath(startPos, endPos, true, true, collideFlags, groundHits); + if (possiblePlatformCount) { - - std::multiset::iterator curRecord; + zVelocity = -FLT_MAX; - for(curRecord = GroundHitRecords.begin(); curRecord != GroundHitRecords.end(); curRecord++) + std::vector::iterator curRecord; + for (curRecord = groundHits.begin(); curRecord != groundHits.end(); ++curRecord) { - hsBool groundlike=false; - if((curRecord->locHit.fZ - startPos.fZ)<= .2) groundlike= true; - if(groundlike) + if (curRecord->ObjHit != nil) { - if(curRecord->ObjHit !=nil) - { - hsVector3 vel; - curRecord->ObjHit->GetLinearVelocitySim(vel); - if(vel.fZ > maxPlatformVel) - { - maxPlatformVel= vel.fZ; - } - } - platformCount ++; + hsVector3 objVelocity; + curRecord->ObjHit->GetLinearVelocitySim(objVelocity); + if (objVelocity.fZ > zVelocity) + zVelocity = objVelocity.fZ; + fGroundHit = true; } } } - - - - bool gotGroundHit = fGroundHit; - if (so) - { - - // If we've been moved since the last physics update (somebody warped us), - // update the physics before we apply velocity. - const hsMatrix44& l2w = so->GetCoordinateInterface()->GetLocalToWorld(); - if (!CompareMatrices(l2w, fCore->GetLastGlobalLoc(), .0001f)) - fCore->SetGlobalLoc(l2w); - - // Convert our avatar relative velocity to subworld relative - if (!LinearVelocity.IsEmpty()) - { - LinearVelocity = l2w * LinearVelocity; - const plCoordinateInterface* subworldCI = fCore->GetSubworldCI(); - if (subworldCI) - LinearVelocity = subworldCI->GetWorldToLocal() * LinearVelocity; - } - - if(!IsOnGround()) - { - if(!fNeedVelocityOverride) - { - LinearVelocity.fZ= AchievedLinearVelocity.fZ; - } - else - { - LinearVelocity = fOverrideVelocity; - } - } - if(fStartJump) - { - LinearVelocity.fZ =12.0f; - } - if(platformCount) - { - LinearVelocity.fZ = LinearVelocity.fZ + maxPlatformVel; - } - - //probably neeed to do something with contact normals in here - //for false ground stuff - - fFalseGround = false; - hsVector3 testLength = LinearVelocity * delSecs + hsVector3(0.0, 0.0, -0.00f); - // - hsPoint3 desiredDestination= startPos + testLength; - if(!IsOnGround()) - { - if(ICheckMove(startPos, desiredDestination)) - {//we can get there soley by the LinearVelocity - - fNeedVelocityOverride =false; - } - else - { - - fNeedVelocityOverride =true; - fOverrideVelocity = LinearVelocity; - fOverrideVelocity.fZ -= delSecs * 32.f; - } - } - else - { - fNeedVelocityOverride =false; - } - fCore->SetLinearVelocity(LinearVelocity); - - } + return fGroundHit; } -bool plRidingAnimatedPhysicalStrategy::ICheckMove(const hsPoint3& startPos, const hsPoint3& desiredPos) + + +////////////////////////////////////////////////////////////////////////// + +/* +Purpose: + +ANGLE_RAD_2D returns the angle in radians swept out between two rays in 2D. + +Discussion: + +Except for the zero angle case, it should be true that + +ANGLE_RAD_2D(X1,Y1,X2,Y2,X3,Y3) ++ ANGLE_RAD_2D(X3,Y3,X2,Y2,X1,Y1) = 2 * PI + +Modified: + +19 April 1999 + +Author: + +John Burkardt + +Parameters: + +Input, float X1, Y1, X2, Y2, X3, Y3, define the rays +( X1-X2, Y1-Y2 ) and ( X3-X2, Y3-Y2 ) which in turn define the +angle, counterclockwise from ( X1-X2, Y1-Y2 ). + +Output, float ANGLE_RAD_2D, the angle swept out by the rays, measured +in radians. 0 <= ANGLE_DEG_2D < 2 PI. If either ray has zero length, +then ANGLE_RAD_2D is set to 0. +*/ + +static float AngleRad2d( float x1, float y1, float x3, float y3 ) { - //returns false if it believes the end result can't be obtained by pure application of velocity (collides into somthing that it can't climb up) - //used as a way to check if it needs to hack getting there like in jumping - - UInt32 collideFlags = - 1<IsSeeking()) - { - collideFlags|=(1< DynamicHits; - int NumberOfHits=fCore->SweepControllerPath(startPos, desiredPos, true, true, collideFlags, DynamicHits); - - hsPoint3 stepFromPoint; - hsVector3 movementdir(&startPos, &desiredPos); - movementdir.Normalize(); - if(NumberOfHits) - { - hsPoint3 initBottomPos; - fCore->GetPositionSim(initBottomPos); - std::multiset< plControllerSweepRecord >::iterator cur; - hsVector3 testLength(desiredPos - startPos); - bool freeMove=true; - for(cur = DynamicHits.begin(); cur != DynamicHits.end(); cur++) - { - if(movementdir.InnerProduct(cur->Norm)>0.01f) - { - hsVector3 topOfBottomHemAtTimeT=hsVector3(initBottomPos + testLength * cur->TimeHit ); - topOfBottomHemAtTimeT.fZ = topOfBottomHemAtTimeT.fZ + fCore->GetControllerWidth(); - if(cur->locHit.fZ <= (topOfBottomHemAtTimeT.fZ -.5f)) - { - hitBottomOfCapsule=true; - hsVector3 norm= hsVector3(-1*(cur->locHit-topOfBottomHemAtTimeT)); - norm.Normalize(); - IAddContactNormals(norm); - } - else - { - return false; - } - } + float value; + float x; + float y; - } - return true; + x = ( x1 ) * ( x3 ) + ( y1 ) * ( y3 ); + y = ( x1 ) * ( y3 ) - ( y1 ) * ( x3 ); + + if ( x == 0.0 && y == 0.0 ) { + value = 0.0; } - else + else { - return true; - } - -} -void plRidingAnimatedPhysicalStrategy::Update(hsScalar delSecs) -{ - if (!fCore->IsEnabled() || fCore->IsKinematic()) - { - fCore->UpdateSubstepNonPhysical(); - return; - } - fCore->CheckAndHandleAnyStateChanges(); -} -void plRidingAnimatedPhysicalStrategy::PostStep(hsScalar delSecs) -{ - if(!(!fCore->IsEnabled() || fCore->IsKinematic())) - { - if (!fGroundHit && !fFalseGround) - fTimeInAir += delSecs; - else - fTimeInAir = 0.f; - hsVector3 AchievedLinearVelocity, LinearVelocity; - AchievedLinearVelocity = fCore->GetLinearVelocity(); - hsScalar AngularVelocity=fCore->GetAngularVelocity(); - fCore->OverrideAchievedVelocity(AchievedLinearVelocity); - plSceneObject* so = plSceneObject::ConvertNoRef(fOwner->ObjectIsLoaded()); - if (so) + value = atan2 ( y, x ); + + if ( value < 0.0 ) { - fCore->UpdateControllerAndPhysicalRep(); - if (AngularVelocity != 0.f) - { - hsScalar deltaAngle=AngularVelocity*delSecs; - fCore->IncrementAngle( deltaAngle); - } - fCore->UpdateWorldRelativePos(); - fCore->SendCorrectionMessages(); + value = (float)(value + TWO_PI); } - LinearVelocity.Set(0.f, 0.f, 0.f); - AngularVelocity = 0.f; - fCore->SetVelocities(LinearVelocity, AngularVelocity); } - fStartJump = false; + return value; } + diff --git a/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plPhysicalControllerCore.h b/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plPhysicalControllerCore.h index bc96f697..8f56ddc2 100644 --- a/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plPhysicalControllerCore.h +++ b/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plPhysicalControllerCore.h @@ -41,310 +41,284 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com *==LICENSE==*/ #ifndef PLPHYSICALCONTROLLERCORE_H #define PLPHYSICALCONTROLLERCORE_H + #include "hsGeometry3.h" #include "hsMatrix44.h" +#include "hsQuat.h" #include "hsTemplates.h" #include "../pnKeyedObject/plKey.h" #include "../plPhysical/plSimDefs.h" -#include "../pnMessage/plMessage.h" - -#include "hsQuat.h" -#define PHYSX_ONLY_TRIGGER_FROM_KINEMATIC 1 -#define kSLOPELIMIT (cosf(hsScalarDegToRad(55.f))) +#include class plCoordinateInterface; class plPhysical; -class plPXPhysical; +class plMovementStrategy; +class plAGApplicator; class plSwimRegionInterface; -//Replacement for for plPhysicalController stripped out some walk specific code -//plPhysicalControllerCore needs to have movement strategies registered to it these will then -//be called by the controller during the simulation steps. The Strategies need to at least have an -// Apply and Update definition. Everything else should be movement specific. I hope to come back and -//and refactor when I have time this in the future. -enum plControllerCollisionFlags -{ - kSides=1, - kTop= (1<<1), - kBottom=(1<<2), -}; -class plMovementStrategySimulationInterface -{ -public: +#define kSlopeLimit (cosf(hsScalarDegToRad(55.f))) - virtual void Apply(hsScalar delSecs)=0; - virtual void Update(hsScalar delSecs)=0; - //most strategies don't require this. Only the ones that require behavior like a physical or need - //something after the sim step. this used to be taken care of by Update, but this was moved to take care of - //some of the frame lag - virtual void PostStep(hsScalar delSecs){}; - virtual void IAddContactNormals(hsVector3& vec){fContactNormals.Append(vec);} - virtual void AddOnTopOfObject(plPhysical* phys){ fOnTopOf.Append(phys);} - virtual void LeaveAge() - { - fContactNormals.SetCount(0); - fOnTopOf.SetCount(0); - } -protected: - hsTArray fContactNormals; - hsTArray fOnTopOf; +enum plControllerCollisionFlags +{ + kSides = 1, + kTop = (1 << 1), + kBottom = (1 << 2) }; -class plControllerSweepRecord +struct plControllerSweepRecord { -public: plPhysical *ObjHit; - hsPoint3 locHit;//World space - hsScalar TimeHit;//Normalized between 0 and 1 - hsVector3 Norm; + hsPoint3 Point; + hsVector3 Normal; }; -bool operator<(const plControllerSweepRecord left, const plControllerSweepRecord right); + class plPhysicalControllerCore { public: - virtual ~plPhysicalControllerCore(); - virtual void Move(hsVector3 displacement, unsigned int collideWith, unsigned int &collisionResults)=0; - virtual void SetMovementSimulationInterface(plMovementStrategySimulationInterface* strat){fMovementInterface=strat;} - virtual void Apply(hsScalar delSecs); - virtual void Update(hsScalar delSecs); - virtual void PostStep(hsScalar delSecs); - // A disabled avatar doesn't move or accumulate air time if he's off the ground. + plPhysicalControllerCore(plKey ownerSceneObject, hsScalar height, hsScalar radius); + virtual ~plPhysicalControllerCore() { } + + // An ArmatureMod has its own idea about when physics should be enabled/disabled. + // Use plArmatureModBase::EnablePhysics() instead. virtual void Enable(bool enable) = 0; - virtual bool IsEnabled() {return fEnabled;} - virtual plKey GetSubworld() {return fWorldKey;} + virtual bool IsEnabled() { return fEnabled; } + + // Subworld + virtual plKey GetSubworld() { return fWorldKey; } virtual void SetSubworld(plKey world) = 0; - virtual const plCoordinateInterface* GetSubworldCI() const = 0; + virtual const plCoordinateInterface* GetSubworldCI(); + // For the avatar SDL only virtual void GetState(hsPoint3& pos, float& zRot) = 0; virtual void SetState(const hsPoint3& pos, float zRot) = 0; - // kinematic stuff .... should be just for when playing a behavior... - virtual void Kinematic(bool state) = 0; - virtual bool IsKinematic() = 0; - virtual void GetKinematicPosition(hsPoint3& pos) = 0; - virtual const hsMatrix44& GetPrevSubworldW2L() = 0; - //when seeking no longer want to interact with exclusion regions - virtual void SetSeek(bool seek){fSeeking=seek;} - virtual bool IsSeeking(){return fSeeking;} - static plPhysicalControllerCore* Create(plKey ownerSO, hsScalar height, hsScalar radius); - virtual plMovementStrategySimulationInterface* GetMovementInterface(){return fMovementInterface;} - plPhysicalControllerCore(plKey ownerSceneObject, hsScalar height, hsScalar radius); - virtual plKey GetOwner(){return fOwner;}; - // Set the LOS DB this avatar will be in (only one) - virtual void SetLOSDB(plSimDefs::plLOSDB losDB) { fLOSDB = losDB; } ; - virtual plSimDefs::plLOSDB GetLOSDB() {return fLOSDB ; } - virtual const hsMatrix44& GetLastGlobalLoc()=0; - virtual void SetKinematicLoc(const hsMatrix44& l2w)=0; - virtual void SetGlobalLoc(const hsMatrix44& l2w)=0; - virtual bool IsEnabledChanged(){return fEnableChanged;} - virtual void HandleEnableChanged()=0; - virtual bool IsKinematicChanged(){return fKinematicChanged;} - virtual void GetPositionSim(hsPoint3& pos)=0; - virtual void HandleKinematicChanged()=0; - virtual bool IsKinematicEnableNextUpdate(){return fKinematicEnableNextUpdate;} - virtual void HandleKinematicEnableNextUpdate()=0; - virtual void MoveKinematicToController(hsPoint3& pos)=0; - virtual void UpdateControllerAndPhysicalRep()=0; - virtual void CheckAndHandleAnyStateChanges(); - virtual void UpdateSubstepNonPhysical(); - virtual const hsPoint3& GetLocalPosition()=0; - const hsQuat& GetLocalRotation() { return fLocalRotation; } - virtual void MoveActorToSim(); - - virtual void OverrideAchievedVelocity(hsVector3 newAchievedVel) - {//because of things like superjumps this is needed I'd rather not, but can't help it - fAchievedLinearVelocity=newAchievedVel; - } - //any clean up for the controller should go here - virtual void LeaveAge()=0; - hsVector3 DisplacementLastStep(){return fDisplacementThisStep;} - hsVector3 MeanVelocityForLastStep() - { - hsVector3 vel=fDisplacementThisStep; - return vel/fSimLength; - } - void SendCorrectionMessages(); + + // The LOS DB this avatar is in (only one) + virtual plSimDefs::plLOSDB GetLOSDB() { return fLOSDB; } + virtual void SetLOSDB(plSimDefs::plLOSDB losDB) { fLOSDB = losDB; } + + // Movement strategy + virtual void SetMovementStrategy(plMovementStrategy* strategy) = 0; + + // Global location + virtual const hsMatrix44& GetLastGlobalLoc() { return fLastGlobalLoc; } + virtual void SetGlobalLoc(const hsMatrix44& l2w) = 0; + + // Local sim position + virtual void GetPositionSim(hsPoint3& pos) = 0; + + // Move kinematic controller + virtual void Move(hsVector3 displacement, unsigned int collideWith, unsigned int &collisionResults) = 0; + + // Set linear velocity on dynamic controller + virtual void SetLinearVelocitySim(const hsVector3& linearVel) = 0; + + // Sweep the controller path from startPos through endPos + virtual int SweepControllerPath(const hsPoint3& startPos,const hsPoint3& endPos, hsBool vsDynamics, hsBool vsStatics, + UInt32& vsSimGroups, std::vector& hits) = 0; + + // any clean up for the controller should go here + virtual void LeaveAge() = 0; + + // Local rotation + const hsQuat& GetLocalRotation() const { return fLocalRotation; } void IncrementAngle(hsScalar deltaAngle); - void UpdateWorldRelativePos(); - virtual void SetLinearVelocity(const hsVector3& linearVel){fLinearVelocity=linearVel;} - //should actually be a 3 vector but everywhere else it is assumed to be just around Z - virtual void SetAngularVelocity(const hsScalar angvel){ fAngularVelocity=angvel;} - virtual void SetVelocities(const hsVector3& linearVel, hsScalar angVel) - { - fLinearVelocity=linearVel; - fAngularVelocity=angVel; - } - virtual const hsVector3& GetLinearVelocity() ; - virtual hsScalar GetAngularVelocity(){return fAngularVelocity;} - virtual const hsVector3& GetAchievedLinearVelocity()const {return fAchievedLinearVelocity;} - plPhysical* GetPushingPhysical(); - bool GetFacingPushingPhysical(); - virtual void SetPushingPhysical(plPhysical* pl){fPushingPhysical=pl;} - virtual void SetFacingPushingPhysical(bool ans){fFacingPushingPhysical=ans;} - //To be Used during runtime conversions, say to switch a tall controller to a ball for swimming - virtual void SetControllerDimensions(hsScalar radius, hsScalar height)=0; - virtual hsScalar GetControllerWidth(){return fRadius;} - virtual hsScalar GetControllerHeight(){return fHeight;} - virtual void ResetAchievedLinearVelocity() - { - fAchievedLinearVelocity.Set(0.f,0.f,0.f); - } - virtual int SweepControllerPath(const hsPoint3& startPos,const hsPoint3& endPos, hsBool vsDynamics, hsBool vsStatics, UInt32& vsSimGroups, std::multiset< plControllerSweepRecord >& WhatWasHitOut)=0; - //this should only be used to force a move it could place your head into a wall and that would be good - virtual hsScalar GetHeight() {return fHeight;} - virtual hsScalar GetRadius() {return fRadius;} - //Wether the avatar thing has mass and forces things down or not, and changes the way things move - //This is an attempt fix things like riding on an animated physical - virtual void BehaveLikeAnimatedPhysical(hsBool actLikeAnAnimatedPhys)=0; - virtual hsBool BehavingLikeAnAnimatedPhysical()=0; -protected: + // Linear velocity + void SetLinearVelocity(const hsVector3& linearVel) { fLinearVelocity = linearVel; } + const hsVector3& GetLinearVelocity() const { return fLinearVelocity; } + + // Acheived linear velocity + const hsVector3& GetAchievedLinearVelocity() const { return fAchievedLinearVelocity; } + void OverrideAchievedLinearVelocity(const hsVector3& linearVel) { fAchievedLinearVelocity = linearVel; } + void ResetAchievedLinearVelocity() { fAchievedLinearVelocity.Set(0.f, 0.f, 0.f); } + + // SceneObject + plKey GetOwner() { return fOwner; } + + // When seeking no longer want to interact with exclude regions + void SetSeek(bool seek) { fSeeking = seek; } + bool IsSeeking() const { return fSeeking; } + + // Pushing physical + plPhysical* GetPushingPhysical() const { return fPushingPhysical; } + void SetPushingPhysical(plPhysical* phys) { fPushingPhysical = phys; } + bool GetFacingPushingPhysical() const { return fFacingPushingPhysical; } + void SetFacingPushingPhysical(bool facing) { fFacingPushingPhysical = facing; } + // Controller dimensions + hsScalar GetRadius() const { return fRadius; } + hsScalar GetHeight() const { return fHeight; } + + // Create a new controller instance - Implemented in the physics system + static plPhysicalControllerCore* Create(plKey ownerSO, hsScalar height, hsScalar radius); + +protected: + virtual void IHandleEnableChanged() = 0; + + void IApply(hsScalar delSecs); + void IUpdate(int numSubSteps, hsScalar alpha); + void IUpdateNonPhysical(hsScalar alpha); + + void ISendCorrectionMessages(bool dirtySynch = false); + plKey fOwner; + plKey fWorldKey; + hsScalar fHeight; hsScalar fRadius; - plKey fWorldKey; + plSimDefs::plLOSDB fLOSDB; - bool fSeeking; - bool fEnabled; - bool fEnableChanged; - bool fKinematic; - bool fKinematicEnableNextUpdate; - bool fKinematicChanged; - plMovementStrategySimulationInterface* fMovementInterface; - hsMatrix44 fLastGlobalLoc; - hsPoint3 fLocalPosition; + + plMovementStrategy* fMovementStrategy; + + hsScalar fSimLength; + hsQuat fLocalRotation; + hsPoint3 fLocalPosition; + hsPoint3 fLastLocalPosition; + + hsMatrix44 fLastGlobalLoc; hsMatrix44 fPrevSubworldW2L; - hsVector3 fDisplacementThisStep; - hsScalar fSimLength; - //physical properties hsVector3 fLinearVelocity; - hsScalar fAngularVelocity; hsVector3 fAchievedLinearVelocity; + plPhysical* fPushingPhysical; bool fFacingPushingPhysical; - bool fNeedsResize; + + bool fSeeking; + bool fEnabled; + bool fEnableChanged; }; -class plMovementStrategy: public plMovementStrategySimulationInterface +class plMovementStrategy { public: - virtual void SetControllerCore(plPhysicalControllerCore* core) - { - fCore=core; - fCore->SetMovementSimulationInterface(this); - } - virtual void RefreshConnectionToControllerCore() - { - fCore->SetMovementSimulationInterface(this); - //fCore->SetControllerDimensions(fPreferedControllerWidth,fPreferedControllerHeight); - fCore->BehaveLikeAnimatedPhysical(this->IRequireBehaviourLikeAnAnimatedPhysical()); - } - plMovementStrategy(plPhysicalControllerCore* core); - //should actually be a 3 vector but everywhere else it is assumed to be just around Z - virtual void SetLinearAcceleration(const hsVector3& accel){fLinearAcceleration=accel;} - virtual const hsVector3& GetLinearAcceleration()const{return fLinearAcceleration;} - //should actually be a 3 vector but everywhere else it is assumed to be just around Z - virtual void ResetAchievedLinearVelocity() - { - hsVector3 AchievedLinearVelocity(0.f,0.f,0.f); - if(fCore)fCore->OverrideAchievedVelocity(AchievedLinearVelocity); - } -//proxy functions for Controller Core - virtual hsScalar GetAirTime() const { return fTimeInAir; } - virtual void ResetAirTime() { fTimeInAir = 0.f; } - + plMovementStrategy(plPhysicalControllerCore* controller); + virtual ~plMovementStrategy() { } + + virtual void Apply(hsScalar delSecs) = 0; + virtual void Update(hsScalar delSecs) { } + + virtual void AddContactNormals(hsVector3& vec) { } + virtual void Reset(bool newAge); + virtual bool IsKinematic() { return true; } + protected: - virtual hsBool IRequireBehaviourLikeAnAnimatedPhysical()=0; - virtual void IApplyKinematic(); - plPhysicalControllerCore* fCore; - hsVector3 fLinearAcceleration; - hsScalar fAngularAcceleration; - plKey fOwner; - static const hsScalar kAirTimeThreshold; - hsScalar fTimeInAir; - hsScalar fPreferedControllerWidth; - hsScalar fPreferedControllerHeight; - + plPhysicalControllerCore* fController; +}; + +class plAnimatedMovementStrategy : public plMovementStrategy +{ +public: + plAnimatedMovementStrategy(plAGApplicator* rootApp, plPhysicalControllerCore* controller); + virtual ~plAnimatedMovementStrategy() { } + + void RecalcVelocity(double timeNow, hsScalar elapsed, hsBool useAnim = true); + void SetTurnStrength(hsScalar val) { fTurnStr = val; } + hsScalar GetTurnStrength() const { return fTurnStr; } +private: + void IRecalcLinearVelocity(float elapsed, hsMatrix44 &prevMat, hsMatrix44 &curMat); + void IRecalcAngularVelocity(float elapsed, hsMatrix44 &prevMat, hsMatrix44 &curMat); + + plAGApplicator* fRootApp; + hsVector3 fAnimLinearVel; + hsScalar fAnimAngularVel; + hsScalar fTurnStr; }; -class plWalkingStrategy: public plMovementStrategy +class plWalkingStrategy : public plAnimatedMovementStrategy { public: - plWalkingStrategy(plPhysicalControllerCore* core):plMovementStrategy(core) - { - fGroundHit=false; - fFalseGround=false; - fHitHead=false; - fCore->SetMovementSimulationInterface(this); - fPreferedControllerWidth=core->GetControllerWidth(); - fPreferedControllerHeight=core->GetControllerHeight(); - fOnTopOfAnimatedPhysLastFrame=false; - } - virtual ~plWalkingStrategy(){}; + plWalkingStrategy(plAGApplicator* rootApp, plPhysicalControllerCore* controller); + virtual ~plWalkingStrategy() { } + virtual void Apply(hsScalar delSecs); - virtual void Update(hsScalar delSecs); + virtual void Update(hsScalar delSecs); + + virtual void AddContactNormals(hsVector3& vec); + virtual void Reset(bool newAge); + bool HitGroundInThisAge() const { return fHitGroundInThisAge; } bool IsOnGround() const { return fTimeInAir < kAirTimeThreshold || fFalseGround; } - bool IsOnFalseGround() const { return fFalseGround && !fGroundHit; } - void GroundHit() { fGroundHit = true; } - virtual void IAddContactNormals(hsVector3& vec); - virtual void StartJump(){}; - + + hsScalar GetAirTime() const { return fTimeInAir; } + void ResetAirTime() { fTimeInAir = 0.0f; } + + hsScalar GetImpactTime() const { return fImpactTime; } + const hsVector3& GetImpactVelocity() const { return fImpactVelocity; } + + bool EnableControlledFlight(bool status); + bool IsControlledFlight() const { return fControlledFlight != 0; } + + plPhysical* GetPushingPhysical() const; + bool GetFacingPushingPhysical() const; protected: + static const hsScalar kAirTimeThreshold; + static const hsScalar kControlledFlightThreshold; + + hsTArray fSlidingNormals; + + hsVector3 fImpactVelocity; + hsScalar fImpactTime; + + hsScalar fTimeInAir; - void ICheckForFalseGround(); + hsScalar fControlledFlightTime; + int fControlledFlight; + bool fGroundHit; bool fFalseGround; - bool fHitHead; - bool fOnTopOfAnimatedPhysLastFrame; - hsTArray fPrevSlidingNormals; - virtual hsBool IRequireBehaviourLikeAnAnimatedPhysical(){return true;} + bool fHeadHit; + bool fSliding; + bool fClearImpact; + bool fHitGroundInThisAge; }; -class plSwimStrategy: public plMovementStrategy + +class plSwimStrategy : public plAnimatedMovementStrategy { public: - plSwimStrategy(plPhysicalControllerCore *core); - virtual ~plSwimStrategy(){}; - void SetSurface(plSwimRegionInterface *region, hsScalar surfaceHeight); + plSwimStrategy(plAGApplicator* rootApp, plPhysicalControllerCore* controller); + virtual ~plSwimStrategy() { } + virtual void Apply(hsScalar delSecs); - virtual void Update(hsScalar delSecs); - hsScalar GetBuoyancy() { return fBuoyancy; } - hsBool IsOnGround() { return fOnGround; } - hsBool HadContacts() { return fHadContacts; } - virtual void IAddContactNormals(hsVector3& vec); + + virtual void AddContactNormals(hsVector3& vec); + + void SetSurface(plSwimRegionInterface* region, hsScalar surfaceHeight); + + hsScalar GetBuoyancy() const { return fBuoyancy; } + bool IsOnGround() const { return fOnGround; } + bool HadContacts() const { return fHadContacts; } + protected: - virtual hsBool IRequireBehaviourLikeAnAnimatedPhysical(){return true;} -private: void IAdjustBuoyancy(); + hsScalar fBuoyancy; - hsBool fOnGround; - hsBool fHadContacts; hsScalar fSurfaceHeight; + plSwimRegionInterface *fCurrentRegion; + + bool fOnGround; + bool fHadContacts; }; -class plRidingAnimatedPhysicalStrategy : public plWalkingStrategy + +class plDynamicWalkingStrategy : public plWalkingStrategy { public: - plRidingAnimatedPhysicalStrategy(plPhysicalControllerCore *core ) : - fNeedVelocityOverride(false),fStartJump(false),plWalkingStrategy(core){}; - virtual ~plRidingAnimatedPhysicalStrategy(){}; + plDynamicWalkingStrategy(plAGApplicator* rootApp, plPhysicalControllerCore* controller); + virtual ~plDynamicWalkingStrategy() { } + virtual void Apply(hsScalar delSecs); - virtual void Update(hsScalar delSecs); - virtual void PostStep(hsScalar delSecs); - bool IsOnGround() const { return fTimeInAir < kAirTimeThreshold || fFalseGround; } - bool IsOnFalseGround() const { return fFalseGround && !fGroundHit; } - void GroundHit() { fGroundHit = true; } - virtual void StartJump(){fStartJump = true;} + + virtual bool IsKinematic() { return false; } + protected: - virtual hsBool IRequireBehaviourLikeAnAnimatedPhysical(){return false;} - bool ICheckMove(const hsPoint3& startPos, const hsPoint3& desiredPos); - hsBool fNeedVelocityOverride; - hsVector3 fOverrideVelocity; - bool fStartJump; + bool ICheckForGround(hsScalar& zVelocity); }; + #endif// PLPHYSICALCONTROLLERCORE_H + diff --git a/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plInputCore/plSceneInputInterface.cpp b/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plInputCore/plSceneInputInterface.cpp index 4d40e538..57d9ee7c 100644 --- a/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plInputCore/plSceneInputInterface.cpp +++ b/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plInputCore/plSceneInputInterface.cpp @@ -73,7 +73,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com #include "../plAvatar/plArmatureMod.h" #include "../plAvatar/plAvBrain.h" #include "../plAvatar/plAvatarMgr.h" -#include "../plAvatar/plAvCallbackAction.h" +#include "../plAvatar/plPhysicalControllerCore.h" #include "../plModifier/plInterfaceInfoModifier.h" #include "../pnModifier/plLogicModBase.h" #include "../plVault/plVault.h" diff --git a/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plModifier/plExcludeRegionModifier.cpp b/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plModifier/plExcludeRegionModifier.cpp index c1f0d5f2..5872072a 100644 --- a/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plModifier/plExcludeRegionModifier.cpp +++ b/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plModifier/plExcludeRegionModifier.cpp @@ -54,7 +54,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com #include "../plMessage/plAvatarMsg.h" #include "plPhysical.h" #include "../plPhysical/plSimDefs.h" -#include "../plAvatar/plAvCallbackAction.h" #include "../plAvatar/plAvBrainGeneric.h" diff --git a/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plPhysical/plCollisionDetector.cpp b/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plPhysical/plCollisionDetector.cpp index a2ea1df0..5b8f23a8 100644 --- a/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plPhysical/plCollisionDetector.cpp +++ b/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plPhysical/plCollisionDetector.cpp @@ -39,7 +39,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com Mead, WA 99021 *==LICENSE==*/ -#include "../plAvatar/plAvCallbackAction.h" #include "hsTypes.h" #include "plCollisionDetector.h" @@ -65,6 +64,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com #include "../plAvatar/plAvatarMgr.h" #include "../plAvatar/plAvBrainHuman.h" #include "../plAvatar/plAvBrainDrive.h" +#include "../plAvatar/plPhysicalControllerCore.h" #include "../plModifier/plDetectorLog.h" @@ -770,7 +770,7 @@ void plObjectInVolumeAndFacingDetector::ICheckForTrigger() // And are we walking towards it? plArmatureBrain* abrain = armMod->FindBrainByClass(plAvBrainHuman::Index()); //armMod->GetCurrentBrain(); plAvBrainHuman* brain = plAvBrainHuman::ConvertNoRef(abrain); - if (brain && brain->IsMovingForward() && brain->fCallbackAction->IsOnGround()) + if (brain && brain->IsMovingForward() && brain->fWalkingStrategy->IsOnGround()) movingForward = true; } else @@ -940,11 +940,11 @@ hsBool plPanicLinkRegion::MsgReceive(plMessage* msg) plArmatureMod* avMod = IGetAvatarModifier(pCollMsg->fOtherKey); if (avMod) { - hsPoint3 kinPos; + hsPoint3 pos; if (avMod->GetController()) { - avMod->GetController()->GetKinematicPosition(kinPos); - DetectorLogSpecial("Avatar is panic linking. KinPos at %f,%f,%f and is %s",kinPos.fX,kinPos.fY,kinPos.fZ,avMod->GetController()->IsEnabled() ? "enabled" : "disabled"); + avMod->GetController()->GetPositionSim(pos); + DetectorLogSpecial("Avatar is panic linking. Position %f,%f,%f and is %s", pos.fX, pos.fY, pos.fZ, avMod->GetController()->IsEnabled() ? "enabled" : "disabled"); } avMod->PanicLink(fPlayLinkOutAnim); } @@ -1168,4 +1168,4 @@ hsBool plRidingAnimatedPhysicalDetector::MsgReceive(plMessage *msg) return true; } return plSimpleRegionSensor::MsgReceive(msg); -} +} diff --git a/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plPhysical/plSimDefs.h b/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plPhysical/plSimDefs.h index 24b4583e..b98d6f97 100644 --- a/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plPhysical/plSimDefs.h +++ b/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plPhysical/plSimDefs.h @@ -72,25 +72,6 @@ namespace plSimDefs kGroupMax, }; - /** A taxonomy of action types. Crucial for doing things like making sure you don't - do things like attach duplicate actions. */ - enum ActionType - { - kUnknownAction = 0x01, // don't know the type (probably forgot to override GetType()) - kUnknownZAction = 0x02, // unknown type of z-order action - kAntiGravityAction = 0x03, // an action that counters gravity exactly - kUprightAction = 0x04, // an action that keeps an object upright by apply force - kPhysAnimAction = 0x05, // an action that parses keyframed animation into physical information - kConstraint = 0x06, // a general constraint. - kCallbackAction = 0x07, // an action that just hands us the physics "tick" - kPseudoPhysAction = 0x08, // replacement for the physAnim - kAntiGravAction = 0x09, // makes things float in the air - kBasicGroundAction = 0x0a, // for your basic walkAroundOnGround corrections - kHorizontalFreeze = 0x0b, // Let's you fall vertically, but otherwise keeps you in place (generic brains) - - kMaxAction = 0xffff // force 16-bit - }; - /** Different types of line-of-sight requests. */ enum LOSReqType {