1
0
mirror of https://foundry.openuru.org/gitblit/r/CWE-ou-minkata.git synced 2025-07-17 10:52:46 +00:00

Merge pull request #206 from Hoikas/quabs

Engine fixes for AhnyQuabs
This commit is contained in:
Branan Purvine-Riley
2012-06-10 09:50:25 -07:00
17 changed files with 158 additions and 106 deletions

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -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()
{

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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();

View File

@ -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
//

View File

@ -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);

View File

@ -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