mirror of
https://foundry.openuru.org/gitblit/r/CWE-ou-minkata.git
synced 2025-07-17 10:52:46 +00:00
@ -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;
|
||||
fNextMode = IPickBehavior(kRun);
|
||||
// TODO: Pathfinding here!
|
||||
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);
|
||||
// Missing TODO Turd: Pathfinding.
|
||||
}
|
||||
|
||||
bool plAvBrainCritter::AtGoal() const
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
msg->Send();
|
||||
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);
|
||||
|
||||
@ -309,9 +310,15 @@ 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 (originating)
|
||||
fLocalPlayerKey = cloneKey;
|
||||
else
|
||||
AddRemotePlayerKey(cloneKey);
|
||||
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