diff --git a/Sources/Plasma/FeatureLib/pfPython/cyMisc.cpp b/Sources/Plasma/FeatureLib/pfPython/cyMisc.cpp index a86bfac9..613662e6 100644 --- a/Sources/Plasma/FeatureLib/pfPython/cyMisc.cpp +++ b/Sources/Plasma/FeatureLib/pfPython/cyMisc.cpp @@ -2868,14 +2868,7 @@ PyObject* cyMisc::GetAIAvatarsByModelName(const char* name) Py_DECREF(tuple); } } - - if (PyList_Size(avList) > 0) - return avList; - else - { - Py_DECREF(avList); - PYTHON_RETURN_NONE; - } + return avList; } void cyMisc::ForceVaultNodeUpdate(unsigned nodeId) diff --git a/Sources/Plasma/FeatureLib/pfPython/pyCritterBrain.cpp b/Sources/Plasma/FeatureLib/pfPython/pyCritterBrain.cpp index 29cbf16f..3ac6a550 100644 --- a/Sources/Plasma/FeatureLib/pfPython/pyCritterBrain.cpp +++ b/Sources/Plasma/FeatureLib/pfPython/pyCritterBrain.cpp @@ -41,8 +41,10 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com *==LICENSE==*/ #include "pyCritterBrain.h" #include "pyGeometry3.h" +#include "pySceneObject.h" #include "plAvatar/plAvBrainCritter.h" +#include "pnSceneObject/plSceneObject.h" pyCritterBrain::pyCritterBrain(): fBrain(nil) {} @@ -66,18 +68,12 @@ void pyCritterBrain::RemoveReceiver(pyKey& oldReceiver) fBrain->RemoveReceiver(oldReceiver.getKey()); } -void pyCritterBrain::LocallyControlled(bool local) +PyObject* pyCritterBrain::GetSceneObject() { - if (!fBrain) - return; - fBrain->LocallyControlled(local); -} - -bool pyCritterBrain::LocallyControlled() const -{ - if (!fBrain) - return false; - return fBrain->LocallyControlled(); + if (fBrain) + if (plSceneObject* obj = fBrain->GetTarget()) + return pySceneObject::New(obj->GetKey()); + PYTHON_RETURN_NONE; } void pyCritterBrain::AddBehavior(const std::string& animationName, const std::string& behaviorName, bool loop /* = true */, diff --git a/Sources/Plasma/FeatureLib/pfPython/pyCritterBrain.h b/Sources/Plasma/FeatureLib/pfPython/pyCritterBrain.h index 28bb3eb4..d6566b26 100644 --- a/Sources/Plasma/FeatureLib/pfPython/pyCritterBrain.h +++ b/Sources/Plasma/FeatureLib/pfPython/pyCritterBrain.h @@ -83,8 +83,7 @@ public: void AddReceiver(pyKey& newReceiver); void RemoveReceiver(pyKey& oldReceiver); - void LocallyControlled(bool local); - bool LocallyControlled() const; + PyObject* GetSceneObject(); void AddBehavior(const std::string& animationName, const std::string& behaviorName, bool loop = true, bool randomStartPos = true, float fadeInLen = 2.f, float fadeOutLen = 2.f); diff --git a/Sources/Plasma/FeatureLib/pfPython/pyCritterBrainGlue.cpp b/Sources/Plasma/FeatureLib/pfPython/pyCritterBrainGlue.cpp index da1435a6..8bf16494 100644 --- a/Sources/Plasma/FeatureLib/pfPython/pyCritterBrainGlue.cpp +++ b/Sources/Plasma/FeatureLib/pfPython/pyCritterBrainGlue.cpp @@ -139,21 +139,9 @@ PYTHON_METHOD_DEFINITION(ptCritterBrain, removeReceiver, args) PYTHON_RETURN_NONE; } -PYTHON_METHOD_DEFINITION(ptCritterBrain, setLocallyControlled, args) +PYTHON_METHOD_DEFINITION(ptCritterBrain, getSceneObject, GetSceneObject) { - char local; - if (!PyArg_ParseTuple(args, "b", &local)) - { - PyErr_SetString(PyExc_TypeError, "setLocallyControlled expects a boolean"); - PYTHON_RETURN_ERROR; - } - self->fThis->LocallyControlled(local != 0); - PYTHON_RETURN_NONE; -} - -PYTHON_METHOD_DEFINITION_NOARGS(ptCritterBrain, getLocallyControlled) -{ - PYTHON_RETURN_BOOL(self->fThis->LocallyControlled()); + return self->fThis->GetSceneObject(); } PYTHON_METHOD_DEFINITION_WKEY(ptCritterBrain, addBehavior, args, keywords) @@ -472,10 +460,7 @@ PYTHON_METHOD_DEFINITION(ptCritterBrain, vectorToPlayer, args) PYTHON_START_METHODS_TABLE(ptCritterBrain) PYTHON_METHOD(ptCritterBrain, addReceiver, "Params: key\nTells the brain that the specified key wants AI messages"), PYTHON_METHOD(ptCritterBrain, removeReceiver, "Params: key\nTells the brain that the specified key no longer wants AI messages"), - PYTHON_METHOD(ptCritterBrain, setLocallyControlled, "Params: local\nTells the brain that we are the ones making all the AI decisions, and to prop location " - "and other information to the server."), - PYTHON_METHOD_NOARGS(ptCritterBrain, getLocallyControlled, "Are we the one making AI decisions? NOTE: Not set automatically, some python script needs to " - "tell the brain this using setLocallyControlled()."), + PYTHON_METHOD(ptCritterBrain, getSceneObject, "Returns the ptSceneObject this brain controls."), PYTHON_METHOD_WKEY(ptCritterBrain, addBehavior, "Params: animName, behaviorName, loop = 1, randomStartPos = 1, fadeInLen = 2.0, fadeOutLen = 2.0\n" "Adds a new animation to the brain as a behavior with the specified name and parameters. If multiple animations are assigned to the same behavior, " "they will be randomly picked from when started."), diff --git a/Sources/Plasma/PubUtilLib/plAvatar/plArmatureMod.cpp b/Sources/Plasma/PubUtilLib/plAvatar/plArmatureMod.cpp index 3e8c27cb..3f7110ef 100644 --- a/Sources/Plasma/PubUtilLib/plAvatar/plArmatureMod.cpp +++ b/Sources/Plasma/PubUtilLib/plAvatar/plArmatureMod.cpp @@ -1952,10 +1952,10 @@ hsBool plArmatureMod::IsLocalAvatar() hsBool plArmatureMod::IsLocalAI() { - plAvBrainCritter* ai = plAvBrainCritter::ConvertNoRef(FindBrainByClass(plAvBrainCritter::Index())); - if (ai) - return ai->LocallyControlled(); - return false; // not an AI, obviously not local + // Formerly a lot of silly cached rigamaroll... Now, we'll just rely + // on the fact that one player is the game master. HACK TURD if net groups + // are ever brought back. + return plNetClientApp::GetInstance()->IsLocallyOwned(this); } void plArmatureMod::SynchIfLocal(double timeNow, int force) diff --git a/Sources/Plasma/PubUtilLib/plAvatar/plAvBrainCritter.cpp b/Sources/Plasma/PubUtilLib/plAvatar/plAvBrainCritter.cpp index 9fd821ed..5ebd4df6 100644 --- a/Sources/Plasma/PubUtilLib/plAvatar/plAvBrainCritter.cpp +++ b/Sources/Plasma/PubUtilLib/plAvatar/plAvBrainCritter.cpp @@ -126,7 +126,7 @@ protected: /////////////////////////////////////////////////////////////////////////////// plAvBrainCritter::plAvBrainCritter(): fCallbackAction(nil), fCurMode(kIdle), fNextMode(kIdle), fFadingNextBehavior(true), - fLocallyControlled(false), fAvoidingAvatars(false), fFinalGoalPos(0, 0, 0), fImmediateGoalPos(0, 0, 0), fDotGoal(0), + fAvoidingAvatars(false), fFinalGoalPos(0, 0, 0), fImmediateGoalPos(0, 0, 0), fDotGoal(0), fAngRight(0) { SightCone(M_PI/2); // 90deg @@ -229,6 +229,13 @@ void plAvBrainCritter::Resume() plArmatureBrain::Resume(); } +plSceneObject* plAvBrainCritter::GetTarget() const +{ + if (fArmature) + return fArmature->GetTarget(0); + return nil; +} + void plAvBrainCritter::AddBehavior(const std::string& animationName, const std::string& behaviorName, bool loop /* = true */, bool randomStartPos /* = true */, float fadeInLen /* = 2.f */, float fadeOutLen /* = 2.f */) { diff --git a/Sources/Plasma/PubUtilLib/plAvatar/plAvBrainCritter.h b/Sources/Plasma/PubUtilLib/plAvatar/plAvBrainCritter.h index dd89f40c..27d2b8c9 100644 --- a/Sources/Plasma/PubUtilLib/plAvatar/plAvBrainCritter.h +++ b/Sources/Plasma/PubUtilLib/plAvatar/plAvBrainCritter.h @@ -83,13 +83,20 @@ public: virtual void Suspend(); virtual void Resume(); + /** + * Gets the SceneObject root for this avatar + * + * This is most useful in scripts that need to act upon the SceneObject directly. + * There are other ways of obtaining the SceneObject, but network synchronization often + * makes those ways more difficult than they need to be, so we have included this method + * to make the scripter's life easier. + */ + plSceneObject* GetTarget() const; + void AddBehavior(const std::string& animationName, const std::string& behaviorName, bool loop = true, bool randomStartPos = true, float fadeInLen = 2.f, float fadeOutLen = 2.f); void StartBehavior(const std::string& behaviorName, bool fade = true); bool RunningBehavior(const std::string& behaviorName) const; - - void LocallyControlled(bool local) {fLocallyControlled = local;} - bool LocallyControlled() const {return fLocallyControlled;} std::string BehaviorName(int behavior) const; plString AnimationName(int behavior) const; @@ -157,8 +164,6 @@ protected: 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? - bool fLocallyControlled; // is our local AI script the one making all the choices? - bool fAvoidingAvatars; // are we avoiding avatars to the best of our ability when pathfinding? hsPoint3 fFinalGoalPos; // the location we are pathfinding to hsPoint3 fImmediateGoalPos; // the location of the point we are immediately going towards (not necessarily our final goal)