mirror of
https://foundry.openuru.org/gitblit/r/CWE-ou-minkata.git
synced 2025-07-14 10:37:41 -04:00
@ -2700,7 +2700,7 @@ PyObject* cyMisc::LoadAvatarModel(const char* modelName, pyKey& spawnPoint, cons
|
||||
|
||||
void cyMisc::UnLoadAvatarModel(pyKey& avatar)
|
||||
{
|
||||
plAvatarMgr::GetInstance()->UnLoadAvatar(avatar.getKey(), false);
|
||||
plAvatarMgr::GetInstance()->UnLoadAvatar(avatar.getKey(), false, true);
|
||||
}
|
||||
|
||||
void cyMisc::ForceCursorHidden()
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
void cyMisc::ForceVaultNodeUpdate(unsigned nodeId)
|
||||
|
@ -374,7 +374,8 @@ PYTHON_GLOBAL_METHOD_DEFINITION(PtLoadAvatarModel, args, "Params: modelName, spa
|
||||
return cyMisc::LoadAvatarModel(modelName, *key, userStr.c_str());
|
||||
}
|
||||
|
||||
PYTHON_GLOBAL_METHOD_DEFINITION(PtUnLoadAvatarModel, args, "Params: avatarKey\nUnloads the specified avatar model")
|
||||
PYTHON_GLOBAL_METHOD_DEFINITION(PtUnLoadAvatarModel, args, "Params: avatarKey\nForcibly unloads the specified avatar model.\n"
|
||||
"Do not use this method unless you require fine-grained control of avatar unloading.")
|
||||
{
|
||||
PyObject* keyObj = NULL;
|
||||
if (!PyArg_ParseTuple(args, "O", &keyObj))
|
||||
|
@ -852,6 +852,34 @@ void plPythonFileMod::AddTarget(plSceneObject* sobj)
|
||||
DisplayPythonOutput();
|
||||
}
|
||||
|
||||
// Oversight fix... Sometimes PythonFileMods are loaded after the AgeInitialState is received.
|
||||
// We should really let the script know about that via OnServerInitComplete anyway because it's
|
||||
// not good to make assumptions about game state in workarounds for that method not being called
|
||||
plNetClientApp* na = plNetClientApp::GetInstance();
|
||||
if (!na->GetFlagsBit(plNetClientApp::kLoadingInitialAgeState) &&
|
||||
na->GetFlagsBit(plNetClientApp::kPlayingGame))
|
||||
{
|
||||
plgDispatch::Dispatch()->UnRegisterForExactType(plInitialAgeStateLoadedMsg::Index(), GetKey());
|
||||
plProfile_BeginTiming(PythonUpdate);
|
||||
// call it
|
||||
PyObject* retVal = PyObject_CallMethod(
|
||||
fPyFunctionInstances[kfunc_OnServerInitComplete],
|
||||
(char*)fFunctionNames[kfunc_OnServerInitComplete], nil);
|
||||
if ( retVal == nil )
|
||||
{
|
||||
#ifndef PLASMA_EXTERNAL_RELEASE
|
||||
// for some reason this function didn't, remember that and not call it again
|
||||
fPyFunctionInstances[kfunc_OnServerInitComplete] = nil;
|
||||
#endif //PLASMA_EXTERNAL_RELEASE
|
||||
// if there was an error make sure that the stderr gets flushed so it can be seen
|
||||
ReportError();
|
||||
}
|
||||
Py_XDECREF(retVal);
|
||||
plProfile_EndTiming(PythonUpdate);
|
||||
// display any output (NOTE: this would be disabled in production)
|
||||
DisplayPythonOutput();
|
||||
}
|
||||
|
||||
// display python output
|
||||
DisplayPythonOutput();
|
||||
}
|
||||
|
@ -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 */,
|
||||
|
@ -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);
|
||||
|
@ -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."),
|
||||
|
@ -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)
|
||||
|
@ -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 */)
|
||||
{
|
||||
@ -310,9 +317,13 @@ std::string plAvBrainCritter::RunBehaviorName() const
|
||||
void plAvBrainCritter::GoToGoal(hsPoint3 newGoal, bool avoidingAvatars /* = false */)
|
||||
{
|
||||
fFinalGoalPos = newGoal;
|
||||
fAvoidingAvatars = avoidingAvatars;
|
||||
fAvoidingAvatars = avoidingAvatars; // TODO: make this do something?
|
||||
|
||||
// Only play the run behavior if it's not already activated
|
||||
// Why? This might just be an update to a preexisting goal.
|
||||
if(!RunningBehavior(RunBehaviorName()))
|
||||
fNextMode = IPickBehavior(kRun);
|
||||
// TODO: Pathfinding here!
|
||||
// Missing TODO Turd: Pathfinding.
|
||||
}
|
||||
|
||||
bool plAvBrainCritter::AtGoal() const
|
||||
|
@ -83,14 +83,21 @@ 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;
|
||||
int CurBehavior() const {return fCurMode;}
|
||||
@ -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)
|
||||
|
@ -217,11 +217,17 @@ plKey plAvatarMgr::LoadAvatar(const char *name, const char *accountName, bool is
|
||||
return result;
|
||||
}
|
||||
|
||||
void plAvatarMgr::UnLoadAvatar(plKey avatarKey, bool isPlayer)
|
||||
void plAvatarMgr::UnLoadAvatar(const plKey& avatarKey, bool isPlayer, bool netPropagate) const
|
||||
{
|
||||
hsBool isLoading = false;
|
||||
plLoadAvatarMsg *msg = new plLoadAvatarMsg(avatarKey, GetKey(), 0, isPlayer, isLoading);
|
||||
if (avatarKey)
|
||||
{
|
||||
plKey requestor = GetKey();
|
||||
plLoadAvatarMsg* msg = new plLoadAvatarMsg(avatarKey, requestor, 0, isPlayer, false);
|
||||
|
||||
// only netprop if the user has a death wish
|
||||
msg->SetBCastFlag(plMessage::kNetPropagate, netPropagate);
|
||||
msg->Send();
|
||||
}
|
||||
}
|
||||
|
||||
// our player's already loaded locally, but we've just linked into an age and others there need to be
|
||||
@ -271,22 +277,6 @@ bool plAvatarMgr::UnPropagateLocalPlayer()
|
||||
return false;
|
||||
}
|
||||
|
||||
// UNLOADREMOTEPLAYER
|
||||
void plAvatarMgr::UnLoadRemotePlayer(plKey remotePlayer)
|
||||
{
|
||||
if(remotePlayer)
|
||||
{
|
||||
plKey requestor = GetKey();
|
||||
bool isPlayer = true;
|
||||
hsBool isLoading = false;
|
||||
plLoadAvatarMsg * msg = new plLoadAvatarMsg(remotePlayer, requestor, 0, isPlayer, isLoading);
|
||||
|
||||
// don't propagate over the network. this is just for removing our local version
|
||||
msg->SetBCastFlag(plMessage::kNetPropagate, false);
|
||||
msg->Send();
|
||||
}
|
||||
}
|
||||
|
||||
// UNLOADLOCALPLAYER
|
||||
void plAvatarMgr::UnLoadLocalPlayer()
|
||||
{
|
||||
|
@ -115,15 +115,21 @@ public:
|
||||
plKey LoadPlayer(const char* name, const char *account);
|
||||
plKey LoadPlayer(const char* name, const char *account, const char *linkName);
|
||||
plKey LoadAvatar(const char *name, const char *accountName, bool isPlayer, plKey spawnPoint, plAvTask *initialTask, const char *userStr = nil);
|
||||
/** Unload an avatar - player or npc - both locally and remotely. */
|
||||
void UnLoadAvatar(plKey avKey, bool isPlayer);
|
||||
|
||||
/**
|
||||
* Unload an avatar clone
|
||||
*
|
||||
* This unloads the clone of an avatar (remote player or NPC) from our local game.
|
||||
* The avatar clone can be unloaded globally by setting netPropagate; however, this
|
||||
* is highly discouraged.
|
||||
*/
|
||||
void UnLoadAvatar(const plKey& avKey, bool isPlayer, bool netPropagate=false) const;
|
||||
/** send our (already loaded) local player to newly-associated clients - used when linking */
|
||||
void PropagateLocalPlayer(int spawnPoint = -1);
|
||||
/** Unload our local player on other machines because we're leaving this age.
|
||||
The player will stay around on our local machine, though. */
|
||||
bool UnPropagateLocalPlayer();
|
||||
|
||||
void UnLoadRemotePlayer(plKey playerKey);
|
||||
void UnLoadLocalPlayer();
|
||||
|
||||
void AddAvatar(plArmatureMod *avatar);
|
||||
|
@ -99,16 +99,6 @@ void plNPCSpawnMod::AddTarget(plSceneObject* so)
|
||||
Trigger();
|
||||
}
|
||||
|
||||
void plNPCSpawnMod::RemoveTarget(plSceneObject *so)
|
||||
{
|
||||
plSingleModifier::RemoveTarget(so);
|
||||
|
||||
if(fSpawnedKey)
|
||||
{
|
||||
plAvatarMgr::GetInstance()->UnLoadAvatar(fSpawnedKey, false);
|
||||
}
|
||||
}
|
||||
|
||||
// TRIGGER
|
||||
bool plNPCSpawnMod::Trigger()
|
||||
{
|
||||
@ -123,6 +113,7 @@ bool plNPCSpawnMod::Trigger()
|
||||
// spawn the NPC
|
||||
plKey spawnPoint = GetTarget(0)->GetKey();
|
||||
|
||||
// Note: we will be unloaded by the NetApp's NPC magick
|
||||
fSpawnedKey = plAvatarMgr::GetInstance()->LoadAvatar(fModelName, fAccountName, false, spawnPoint, nil);
|
||||
|
||||
ISendNotify(fSpawnedKey);
|
||||
|
@ -58,7 +58,6 @@ public:
|
||||
GETINTERFACE_ANY( plNPCSpawnMod, plSingleModifier );
|
||||
|
||||
virtual void AddTarget(plSceneObject* so);
|
||||
virtual void RemoveTarget(plSceneObject *so);
|
||||
// hsBool MsgReceive(plMessage* msg);
|
||||
|
||||
virtual void Read(hsStream *stream, hsResMgr *mgr);
|
||||
|
@ -223,6 +223,7 @@ void plNCAgeLeaver::ExecNextOp () {
|
||||
plAgeLoader::GetInstance()->UnloadAge(); // unload age
|
||||
nc->ISendCameraReset(false/*leaving age*/); // reset camera
|
||||
nc->IUnloadRemotePlayers(); // unload other players
|
||||
nc->IUnloadNPCs(); // unload non-player clones
|
||||
|
||||
if (NetCommNeedToLoadAvatar())
|
||||
am->UnLoadLocalPlayer();
|
||||
|
@ -181,13 +181,9 @@ void plNetClientMgr::Shutdown()
|
||||
|
||||
plNetLinkingMgr::GetInstance()->LeaveAge(true);
|
||||
|
||||
// release existing remote players
|
||||
int i;
|
||||
for (i=0;i<RemotePlayerKeys().size();i++)
|
||||
{
|
||||
plKey k=RemotePlayerKeys()[i];
|
||||
plAvatarMgr::GetInstance()->UnLoadRemotePlayer(k);
|
||||
}
|
||||
// release all avatar clones
|
||||
IUnloadRemotePlayers();
|
||||
IUnloadNPCs();
|
||||
|
||||
// Finally, pump the dispatch system so all the new refs get delivered.
|
||||
plgDispatch::Dispatch()->MsgQueueProcess();
|
||||
@ -197,7 +193,7 @@ void plNetClientMgr::Shutdown()
|
||||
delete fMsgRecorder;
|
||||
fMsgRecorder = nil;
|
||||
}
|
||||
for (i = 0; i < fMsgPlayers.size(); i++)
|
||||
for (int i = 0; i < fMsgPlayers.size(); i++)
|
||||
delete fMsgPlayers[i];
|
||||
fMsgPlayers.clear();
|
||||
|
||||
@ -424,9 +420,19 @@ int plNetClientMgr::IPrepMsg(plNetMessage* msg)
|
||||
//
|
||||
void plNetClientMgr::IUnloadRemotePlayers()
|
||||
{
|
||||
for(int i=RemotePlayerKeys().size()-1;i>=0;i--)
|
||||
plAvatarMgr::GetInstance()->UnLoadRemotePlayer(RemotePlayerKeys()[i]);
|
||||
hsAssert(!RemotePlayerKeys().size(),"Still remote players left when linking out");
|
||||
for (size_t i = fRemotePlayerKeys.size(); i > 0; --i)
|
||||
plAvatarMgr::GetInstance()->UnLoadAvatar(fRemotePlayerKeys[i-1], true);
|
||||
hsAssert(fRemotePlayerKeys.empty(), "Still remote players left when linking out");
|
||||
}
|
||||
|
||||
//
|
||||
// unload NPCs since we're leaving the age
|
||||
//
|
||||
void plNetClientMgr::IUnloadNPCs()
|
||||
{
|
||||
for (size_t i = fNPCKeys.size(); i > 0; --i)
|
||||
plAvatarMgr::GetInstance()->UnLoadAvatar(fNPCKeys[i-1], false);
|
||||
hsAssert(fNPCKeys.empty(), "Still npcs left when linking out");
|
||||
}
|
||||
|
||||
//
|
||||
@ -853,6 +859,31 @@ plSynchedObject* plNetClientMgr::GetLocalPlayer(hsBool forceLoad) const
|
||||
plSynchedObject::ConvertNoRef(fLocalPlayerKey->ObjectIsLoaded()) : nil;
|
||||
}
|
||||
|
||||
plSynchedObject* plNetClientMgr::GetNPC(uint32_t i) const
|
||||
{
|
||||
return fNPCKeys[i] ? plSynchedObject::ConvertNoRef(fNPCKeys[i]->ObjectIsLoaded()) : nil;
|
||||
}
|
||||
|
||||
void plNetClientMgr::AddNPCKey(const plKey& npc)
|
||||
{
|
||||
// note: npc keys have little sanity checking...
|
||||
hsAssert(npc, "adding nil npc key? naughty, naughty...");
|
||||
fNPCKeys.push_back(npc);
|
||||
}
|
||||
|
||||
bool plNetClientMgr::IsNPCKey(const plKey& npc, int* idx) const
|
||||
{
|
||||
if (npc)
|
||||
{
|
||||
plKeyVec::const_iterator it = std::find(fNPCKeys.begin(), fNPCKeys.end(), npc);
|
||||
bool found = it != fNPCKeys.end();
|
||||
if (idx)
|
||||
*idx = found ? (it - fNPCKeys.begin()) : -1;
|
||||
return found;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// return a ptr to a remote player
|
||||
//
|
||||
|
@ -153,7 +153,7 @@ private:
|
||||
// cached char info
|
||||
plKey fLocalPlayerKey;
|
||||
plKeyVec fRemotePlayerKeys;
|
||||
// plKeyVec fNPCKeys;
|
||||
plKeyVec fNPCKeys;
|
||||
|
||||
class plNetClientMgrMsg * fDisableMsg;
|
||||
|
||||
@ -222,6 +222,7 @@ private:
|
||||
void IRemoveCloneRoom();
|
||||
|
||||
void IUnloadRemotePlayers();
|
||||
void IUnloadNPCs();
|
||||
|
||||
plKey ILoadClone(plLoadCloneMsg *cloneMsg);
|
||||
|
||||
@ -310,8 +311,14 @@ public:
|
||||
// avatar vault actions
|
||||
int UploadPlayerVault(uint32_t vaultFlags);
|
||||
|
||||
// npc clones
|
||||
const plKeyVec& NPCKeys() const { return fNPCKeys; }
|
||||
plSynchedObject* GetNPC(uint32_t i) const;
|
||||
void AddNPCKey(const plKey& npc);
|
||||
bool IsNPCKey(const plKey& npc, int* idx=nil) const;
|
||||
|
||||
// remote players
|
||||
const std::vector<plKey>& RemotePlayerKeys() const { return fRemotePlayerKeys; }
|
||||
const plKeyVec& RemotePlayerKeys() const { return fRemotePlayerKeys; }
|
||||
plSynchedObject* GetRemotePlayer(int i) const;
|
||||
void AddRemotePlayerKey(plKey p);
|
||||
hsBool IsRemotePlayerKey(const plKey p, int* idx=nil);
|
||||
|
@ -113,13 +113,16 @@ plKey plNetClientMgr::ILoadClone(plLoadCloneMsg *pCloneMsg)
|
||||
|
||||
// check if local or remote player before loading
|
||||
plLoadAvatarMsg* loadAvMsg=plLoadAvatarMsg::ConvertNoRef(pCloneMsg);
|
||||
if (loadAvMsg && loadAvMsg->GetIsPlayer())
|
||||
if (loadAvMsg)
|
||||
{
|
||||
bool originating = ( pCloneMsg->GetOriginatingPlayerID() == this->GetPlayerID() );
|
||||
if (loadAvMsg->GetIsPlayer())
|
||||
if (originating)
|
||||
fLocalPlayerKey = cloneKey;
|
||||
else
|
||||
AddRemotePlayerKey(cloneKey);
|
||||
else // hey, we got a quab or yeesha... or some other such devilry...
|
||||
AddNPCKey(cloneKey);
|
||||
}
|
||||
|
||||
plKey cloneNodeKey = hsgResMgr::ResMgr()->FindKey(kNetClientCloneRoom_KEY);
|
||||
@ -139,6 +142,12 @@ plKey plNetClientMgr::ILoadClone(plLoadCloneMsg *pCloneMsg)
|
||||
return cloneKey;
|
||||
}
|
||||
|
||||
// need to drop our ref if it's an NPC
|
||||
// remote players handled by plPlayerPageMsg--don't sweat that
|
||||
plKeyVec::iterator it = std::find(fNPCKeys.begin(), fNPCKeys.end(), cloneKey);
|
||||
if (it != fNPCKeys.end())
|
||||
fNPCKeys.erase(it);
|
||||
|
||||
ICheckPendingStateLoad(hsTimer::GetSysSeconds());
|
||||
plSynchEnabler p(false); // turn off dirty tracking while in this function
|
||||
|
||||
|
Reference in New Issue
Block a user