/*==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 . 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 "cyAvatar.h" #include "plgDispatch.h" #include "../plAvatar/plAvatarMgr.h" #include "../plMessage/plAvatarMsg.h" #include "../plMessage/plLinkToAgeMsg.h" #include "../plMessage/plOneShotCallbacks.h" #include "../plMessage/plOneShotMsg.h" #include "../plMessage/plMultistageMsg.h" #include "../pnMessage/plNotifyMsg.h" #include "../pnKeyedObject/plFixedKey.h" #include "../plGImage/plMipmap.h" #include "pyKey.h" #include "pySceneObject.h" #include "pyColor.h" #include "pyImage.h" #include "cyPythonInterface.h" #include "cyMisc.h" #include "../plAvatar/plOneShotMod.h" #include "../plAvatar/plMultistageBehMod.h" #include "../plAvatar/plAvatarClothing.h" #include "../plAvatar/plClothingLayout.h" #include "../plAvatar/plArmatureMod.h" #include "../plAvatar/plAvBrainHuman.h" // needed to call the emote #include "../plAvatar/plAGAnim.h" // to get the BodyUsage enum #include "../plInputCore/plAvatarInputInterface.h" #include "plPhysical.h" #include "../plMessage/plSimStateMsg.h" #include "../pnNetCommon/plNetApp.h" #include "../plVault/plVault.h" #include "../plDrawable/plSharedMesh.h" #include "../pnSceneObject/plSceneObject.h" #include "../pnSceneObject/plCoordinateInterface.h" #include "../plDrawable/plMorphSequence.h" /////////////////////////////////////////////////////////////////////////// // // LOCAL FORWARD DECLs // /////////////////////////////////////////////////////////////////////////// bool IEnterGenericMode(const char *enterAnim, const char *idleAnim, const char *exitAnim, bool autoExit, plAGAnim::BodyUsage bodyUsage, plAvBrainGeneric::BrainType = plAvBrainGeneric::kGeneric); bool IExitTopmostGenericMode(); cyAvatar::cyAvatar(plKey sender, plKey recvr) { SetSender(sender); AddRecvr(recvr); fNetForce = false; } // setters void cyAvatar::SetSender(plKey &sender) { fSender = sender; } void cyAvatar::AddRecvr(plKey &recvr) { if ( recvr != nil ) fRecvr.Append(recvr); } void cyAvatar::SetNetForce(hsBool state) { // set our flag fNetForce = state; } void cyAvatar::SetSenderKey(pyKey& pKey) { SetSender(pKey.getKey()); } ///////////////////////////////////////////////////////////////////////////// // // Function : IFindArmatureModKey // PARAMETERS : avObj - avatar sceneobject // // PURPOSE : find the armature mod for this sceneoabject (if its an avatar) // const plArmatureMod* cyAvatar::IFindArmatureMod(plKey avKey) { plSceneObject* avObj = plSceneObject::ConvertNoRef(avKey->ObjectIsLoaded()); if ( avObj ) { // search through its modifiers to see if one of them is an avatar modifier int i; for ( i=0; iGetNumModifiers(); i++ ) { const plModifier* mod = avObj->GetModifier(i); // see if it is an avatar mod base class const plArmatureMod* avmod = plArmatureMod::ConvertNoRef(mod); if ( avmod ) return avmod; } } // otherwise we didn't find anything return nil; } ///////////////////////////////////////////////////////////////////////////// // // Function : IFindArmatureModKey // PARAMETERS : avObj - avatar sceneobject // // PURPOSE : find the armature mod for this sceneoabject (if its an avatar) // plKey cyAvatar::IFindArmatureModKey(plKey avKey) { const plArmatureMod* avatar = IFindArmatureMod(avKey); if ( avatar ) return avatar->GetKey(); // otherwise we didn't find anything return nil; } ///////////////////////////////////////////////////////////////////////////// // // Function : oneShot // PARAMETERS : // // PURPOSE : oneShot Avatar (must already be there) // void cyAvatar::OneShot(pyKey &seekKey, float duration, hsBool usePhysics, const char *animName, hsBool drivable, hsBool reversible) { if ( fRecvr.Count() > 0 ) { // create message plAvOneShotMsg* pMsg = TRACKED_NEW plAvOneShotMsg( (plKey )fSender, nil, seekKey.getKey(), // Mark D told me to do it ...paulg duration, usePhysics, animName, // Constructor will do a copy. -mf- hsStrcpy(animName), drivable, reversible); // check if this needs to be network forced to all clients if (fNetForce ) { // set the network propagate flag to make sure it gets to the other clients pMsg->SetBCastFlag(plMessage::kNetPropagate); pMsg->SetBCastFlag(plMessage::kNetForce); } // must have a receiver! pMsg->SetBCastFlag(plMessage::kPropagateToModifiers); // add all our receivers to the message receiver list int i; for ( i=0; iAddReceiver(fRecvr[i]); } plgDispatch::MsgSend( pMsg ); // whoosh... off it goes } } ///////////////////////////////////////////////////////////////////////////// // // Function : RunBehavior // PARAMETERS : // // PURPOSE : Run Behavior, could be single or multi-stage shot // void cyAvatar::RunBehavior(pyKey &behKey, hsBool netForce, hsBool netProp) { // first there is someone to send to and make sure that we an avatar to send this to if ( behKey.getKey() != nil && fRecvr.Count() > 0) { // must determine if the behKey is pointing to Single or Multi Shot behavior if ( plOneShotMod::ConvertNoRef(behKey.getKey()->GetObjectPtr()) != nil ) { // create a message OneShotMessage plOneShotMsg* pMsg = TRACKED_NEW plOneShotMsg; // check if this needs to be network forced to all clients if (netProp) { pMsg->SetBCastFlag(plMessage::kNetPropagate); } else { pMsg->SetBCastFlag(plMessage::kNetPropagate, false); } if (netForce) { // set the network propagate flag to make sure it gets to the other clients pMsg->SetBCastFlag(plMessage::kNetPropagate); pMsg->SetBCastFlag(plMessage::kNetForce); } else { pMsg->SetBCastFlag(plMessage::kNetForce, false); } pMsg->SetSender(fSender); pMsg->AddReceiver(behKey.getKey()); int i; for ( i=0; ifPlayerKey = (plKey)fRecvr[i]; plgDispatch::MsgSend( pMsg ); // send off command for each valid avatar we find // ... really, should only be one... though } } } // else if it is a Multistage guy else if ( plMultistageBehMod::ConvertNoRef(behKey.getKey()->GetObjectPtr()) != nil ) { // its a multistage thingy... need to send it a plNotifyMsg // create new notify message to do the actual send with plNotifyMsg* pNMsg = TRACKED_NEW plNotifyMsg; // set whether this should be forced over the network (ignoring net-cascading) if (netProp) { pNMsg->SetBCastFlag(plMessage::kNetPropagate); } else { pNMsg->SetBCastFlag(plMessage::kNetPropagate, false); } if ( netForce ) { pNMsg->SetBCastFlag(plMessage::kNetPropagate); pNMsg->SetBCastFlag(plMessage::kNetForce); } else { pNMsg->SetBCastFlag(plMessage::kNetForce, false); } // copy data and event records to new NotifyMsg pNMsg->fState = 1.0; // need to recreate all the events in the new message by Adding them if ( fRecvr.Count() > 0 && fRecvr[0] != nil ) { pNMsg->AddPickEvent( (plKey)fRecvr[0], nil, true, hsPoint3(0,0,0) ); } // add receivers // loop though adding the ones that want to be notified of the change pNMsg->AddReceiver(behKey.getKey()); pNMsg->SetSender(fSender); plgDispatch::MsgSend( pNMsg ); } } } ///////////////////////////////////////////////////////////////////////////// // // Function : RunBehaviorAndReply // PARAMETERS : // // PURPOSE : Run Behavior, multistage only, reply to specified key'd object // void cyAvatar::RunBehaviorAndReply(pyKey& behKey, pyKey& replyKey, hsBool netForce, hsBool netProp) { plMultistageBehMod* pMod = plMultistageBehMod::ConvertNoRef(behKey.getKey()->GetObjectPtr()); if ( pMod ) { // its a multistage thingy... need to send it a plNotifyMsg // create new notify message to do the actual send with plNotifyMsg* pNMsg = TRACKED_NEW plNotifyMsg; // set whether this should be forced over the network (ignoring net-cascading) if (netProp) { pNMsg->SetBCastFlag(plMessage::kNetPropagate); } else { pNMsg->SetBCastFlag(plMessage::kNetPropagate, false); } if (netForce) { // set the network propagate flag to make sure it gets to the other clients pNMsg->SetBCastFlag(plMessage::kNetPropagate); pNMsg->SetBCastFlag(plMessage::kNetForce); } else { pNMsg->SetBCastFlag(plMessage::kNetForce, false); } // copy data and event records to new NotifyMsg pNMsg->fState = 1.0; // need to recreate all the events in the new message by Adding them if ( fRecvr.Count() > 0 && fRecvr[0] != nil ) { pNMsg->AddPickEvent( (plKey)fRecvr[0], nil, true, hsPoint3(0,0,0) ); } // add receivers // loop though adding the ones that want to be notified of the change pNMsg->AddReceiver(behKey.getKey()); pNMsg->SetSender(replyKey.getKey()); plgDispatch::MsgSend( pNMsg ); } } ///////////////////////////////////////////////////////////////////////////// // // Function : NextStage // PARAMETERS : behKey - behavior pyKey // : transTime - the transition time to the next stage // (optional): rewind - whether to rewind to the front of the next stage // // PURPOSE : Go to the next stage in a multi-stage behavior // // NOTE: only works with multi-stage behaviors // void cyAvatar::NextStage(pyKey &behKey, hsScalar transTime, hsBool setTime, hsScalar newTime, hsBool setDirection, bool isForward, hsBool netForce) { // first there is someone to send to and make sure that we an avatar to send this to if ( behKey.getKey() != nil && fRecvr.Count() > 0) { // if it is a Multistage guy if ( plMultistageBehMod::ConvertNoRef(behKey.getKey()->GetObjectPtr()) != nil ) { plKey avKey = IFindArmatureModKey( (plKey)fRecvr[0] ); if ( avKey ) { // create the message plAvBrainGenericMsg* pMsg = TRACKED_NEW plAvBrainGenericMsg((plKey)fSender, avKey, plAvBrainGenericMsg::kNextStage, 0, setTime, newTime, setDirection, (bool)isForward, transTime); if ( netForce ) pMsg->SetBCastFlag(plMessage::kNetForce | plMessage::kNetPropagate); plgDispatch::MsgSend( pMsg ); } } } } ///////////////////////////////////////////////////////////////////////////// // // Function : PreviousStage // PARAMETERS : behKey - behavior pyKey // : transTime - the transition time to the next stage // (optional): rewind - whether to rewind to the front of the next stage // // PURPOSE : Go to the previous stage in a multi-stage behavior // // NOTE: only works with multi-stage behaviors // void cyAvatar::PreviousStage(pyKey &behKey, hsScalar transTime, hsBool setTime, hsScalar newTime, hsBool setDirection, bool isForward, hsBool netForce) { // first there is someone to send to and make sure that we an avatar to send this to if ( behKey.getKey() != nil && fRecvr.Count() > 0) { // if it is a Multistage guy if ( plMultistageBehMod::ConvertNoRef(behKey.getKey()->GetObjectPtr()) != nil ) { plKey avKey = IFindArmatureModKey( (plKey)fRecvr[0] ); if ( avKey ) { // create the message plAvBrainGenericMsg* pMsg = TRACKED_NEW plAvBrainGenericMsg((plKey)fSender, avKey, plAvBrainGenericMsg::kPrevStage, 0, setTime, newTime, setDirection, (bool)isForward, transTime); if ( netForce ) pMsg->SetBCastFlag(plMessage::kNetForce | plMessage::kNetPropagate); plgDispatch::MsgSend( pMsg ); } } } } ///////////////////////////////////////////////////////////////////////////// // // Function : GotoStage // PARAMETERS : behKey - behavior pyKey // : stage - stage number to go to // : transTime - the transition time to the next stage // (optional): rewind - whether to rewind to the front of the next stage // // PURPOSE : Go to a particular stage in a multi-stage behavior // // NOTE: only works with multi-stage behaviors // void cyAvatar::GoToStage(pyKey &behKey, Int32 stage, hsScalar transTime, hsBool setTime, hsScalar newTime, hsBool setDirection, bool isForward, hsBool netForce) { // first there is someone to send to and make sure that we an avatar to send this to if ( behKey.getKey() != nil && fRecvr.Count() > 0) { // if it is a Multistage guy if ( plMultistageBehMod::ConvertNoRef(behKey.getKey()->GetObjectPtr()) != nil ) { plKey avKey = IFindArmatureModKey( (plKey)fRecvr[0] ); if ( avKey ) { // create the message plAvBrainGenericMsg* pMsg = TRACKED_NEW plAvBrainGenericMsg((plKey)fSender, avKey, plAvBrainGenericMsg::kGotoStage, stage, setTime, newTime, setDirection, isForward, transTime); if ( netForce ) pMsg->SetBCastFlag(plMessage::kNetForce | plMessage::kNetPropagate); plgDispatch::MsgSend( pMsg ); } } } } void cyAvatar::SetLoopCount(pyKey &behKey, Int32 stage, Int32 loopCount, hsBool netForce) { // if it is a Multistage guy if ( plMultistageBehMod::ConvertNoRef(behKey.getKey()->GetObjectPtr()) != nil ) { plMultistageModMsg* pMsg = TRACKED_NEW plMultistageModMsg((plKey)nil, behKey.getKey()); pMsg->SetCommand(plMultistageModMsg::kSetLoopCount); pMsg->fStageNum = (UInt8)stage; pMsg->fNumLoops = (UInt8)loopCount; if ( netForce ) pMsg->SetBCastFlag(plMessage::kNetForce | plMessage::kNetPropagate); plgDispatch::MsgSend( pMsg ); } } ///////////////////////////////////////////////////////////////////////////// // // Function : seek // PARAMETERS : // // PURPOSE : seek Avatar (must already be there) // /* Unsupported. Ask Bob if you want it back. void cyAvatar::Seek(pyKey &seekKey, float duration, hsBool usePhysics) { // must have a receiver! if ( fRecvr.Count() > 0 ) { // create message plAvSeekMsg* pMsg = TRACKED_NEW plAvSeekMsg( (plKey)fSender,nil, seekKey.getKey(),duration,usePhysics); // check if this needs to be network forced to all clients if (fNetForce ) { // set the network propagate flag to make sure it gets to the other clients pMsg->SetBCastFlag(plMessage::kNetPropagate); pMsg->SetBCastFlag(plMessage::kNetForce); } pMsg->SetBCastFlag(plMessage::kPropagateToModifiers); // add all our receivers to the message receiver list int i; for ( i=0; iAddReceiver(fRecvr[i]); } plgDispatch::MsgSend( pMsg ); // whoosh... off it goes } } */ ///////////////////////////////////////////////////////////////////////////// // // Function : GetAvatarClothingGroup // PARAMETERS : // // PURPOSE : Return what clothing group the avatar is in // Int32 cyAvatar::GetAvatarClothingGroup() { // find the avatar's armature modifier const plArmatureMod *avMod = nil; // we can really only talk to one avatar, so just get the first one (which is probably the only one) if ( fRecvr.Count() > 0 && fRecvr[0] != nil ) { plSceneObject *so = plSceneObject::ConvertNoRef(fRecvr[0]->GetObjectPtr()); if (so != nil) { avMod = (plArmatureMod*)so->GetModifierByType(plArmatureMod::Index()); if ( avMod ) { return avMod->GetClothingOutfit()->fGroup; } } } return -1; } ///////////////////////////////////////////////////////////////////////////// // // Function : GetClosetClothingList // PARAMETERS : // // PURPOSE : Return a list of the wearable items for this avatar of that clothing_type // std::vector cyAvatar::GetEntireClothingList(Int32 clothing_type) { // Currently, just all the clothing available will be returned hsTArray clothingList = plClothingMgr::GetClothingMgr()->GetItemList(); int numItems = clothingList.GetCount(); // create the string list to send to python... std::vector retVal; for (int i = 0; i < numItems; i++) retVal.push_back(clothingList[i]->GetName()); return retVal; } ///////////////////////////////////////////////////////////////////////////// // // Function : GetClosetClothingList // PARAMETERS : // // PURPOSE : Return a list of the wearable items for this avatar of that clothing_type // std::vector cyAvatar::GetClosetClothingList(Int32 clothing_type) { std::vector retVal; // find the avatar's armature modifier const plArmatureMod *avMod = nil; // we can really only talk to one avatar, so just get the first one (which is probably the only one) if ( fRecvr.Count() > 0 && fRecvr[0] != nil ) { plSceneObject *so = plSceneObject::ConvertNoRef(fRecvr[0]->GetObjectPtr()); if (so != nil) { avMod = (plArmatureMod*)so->GetModifierByType(plArmatureMod::Index()); if ( avMod ) { // Get all the clothes that we can wear hsTArray clothingList; plClothingMgr::GetClothingMgr()->GetItemsByGroup(avMod->GetClothingOutfit()->fGroup, clothingList); int numItems = clothingList.GetCount(); // create the string list to send to python... as a python object int i; for ( i=0; ifType == clothing_type ) { // add this event record to the main event list (lists within a list) // create list PyObject* clothingItem = PyList_New(5); // [0] = clothing name PyList_SetItem(clothingItem, 0, PyString_FromString(item->GetName())); // [1] = clothing type PyList_SetItem(clothingItem, 1, PyInt_FromLong(item->fType)); // [2] = description const char* description = ""; // assume an empty string if ( item->fDescription != nil ) description = item->fDescription; PyList_SetItem(clothingItem, 2, PyString_FromString(description)); // [3] = ptImage of icon if ( item->fThumbnail != nil ) // create a ptImage PyList_SetItem(clothingItem, 3, pyImage::New(item->fThumbnail->GetKey())); else PyList_SetItem(clothingItem, 3, PyInt_FromLong(0)); // [4] = fCustomText const char* custom = ""; // assume an empty string if ( item->fCustomText != nil ) custom = item->fCustomText; PyList_SetItem(clothingItem, 4, PyString_FromString(custom)); retVal.push_back(clothingItem); } } } } } return retVal; } ///////////////////////////////////////////////////////////////////////////// // // Function : GetAvatarClothingList // PARAMETERS : // // PURPOSE : Return a list of the wearable items for this avatar of that clothing_type // std::vector cyAvatar::GetAvatarClothingList() { std::vector retVal; // find the avatar's armature modifier const plArmatureMod *avMod = nil; // we can really only talk to one avatar, so just get the first one (which is probably the only one) if ( fRecvr.Count() > 0 && fRecvr[0] != nil ) { plSceneObject *so = plSceneObject::ConvertNoRef(fRecvr[0]->GetObjectPtr()); if (so != nil) { avMod = (plArmatureMod*)so->GetModifierByType(plArmatureMod::Index()); if ( avMod ) { // Currently, just all the clothing available will be returned hsTArray clothingList = avMod->GetClothingOutfit()->GetItemList(); int numItems = clothingList.GetCount(); // create the string list to send to python... as a python object int i; for ( i=0; iGetName())); // [1] = clothing type PyList_SetItem(clothingItem, 1, PyInt_FromLong(item->fType)); // [2] = description const char* description = ""; // assume an empty string if ( item->fDescription != nil ) description = item->fDescription; PyList_SetItem(clothingItem, 2, PyString_FromString(description)); // [3] = ptImage of icon if ( item->fThumbnail != nil ) // create a ptImage PyList_SetItem(clothingItem, 3, pyImage::New(item->fThumbnail->GetKey())); else PyList_SetItem(clothingItem, 3, PyInt_FromLong(0)); // [4] = fCustomText const char* custom = ""; // assume an empty string if ( item->fCustomText != nil ) custom = item->fCustomText; PyList_SetItem(clothingItem, 4, PyString_FromString(custom)); retVal.push_back(clothingItem); } } } } return retVal; } ///////////////////////////////////////////////////////////////////////////// // // Function : GetWardrobeClothingList // PARAMETERS : // // PURPOSE : Return a list of items that are in the avatars closet // std::vector cyAvatar::GetWardrobeClothingList() { std::vector retVal; hsTArray closetList; plClothingMgr::GetClothingMgr()->GetClosetItems(closetList); int numItems = closetList.GetCount(); // create the string list to send to python... as a python object int i; for ( i=0; iGetName())); // [1] = clothing type PyList_SetItem(closetItem, 1, PyInt_FromLong(closetList[i].fItem->fType)); // [2] = description const char* description = ""; // assume an empty string if ( closetList[i].fItem->fDescription != nil ) description = closetList[i].fItem->fDescription; PyList_SetItem(closetItem, 2, PyString_FromString(description)); // [3] = ptImage of icon if ( closetList[i].fItem->fThumbnail != nil ) // create a ptImage PyList_SetItem(closetItem, 3, pyImage::New(closetList[i].fItem->fThumbnail->GetKey())); else PyList_SetItem(closetItem, 3, PyInt_FromLong(0)); // [4] = fCustomText const char* custom = ""; // assume an empty string if ( closetList[i].fItem->fCustomText != nil ) custom = closetList[i].fItem->fCustomText; PyList_SetItem(closetItem, 4, PyString_FromString(custom)); // [5] = fTint1 PyList_SetItem(closetItem, 5, pyColor::New(closetList[i].fOptions.fTint1)); // [6] = fTint2 PyList_SetItem(closetItem, 6, pyColor::New(closetList[i].fOptions.fTint2)); retVal.push_back(closetItem); } return retVal; } ///////////////////////////////////////////////////////////////////////////// // // Function : AddWardrobeClothingItem // PARAMETERS : clothing_name - the name of the clothing item to add to your wardrobe // : tint1 - layer one color // : tint2 - layer two color // // PURPOSE : To add a clothing item to the avatar's wardrobe (closet) // void cyAvatar::AddWardrobeClothingItem(const char* clothing_name,pyColor& tint1,pyColor& tint2) { plClothingItem *item = plClothingMgr::GetClothingMgr()->FindItemByName((char*)clothing_name); if ( item ) { hsTArray items; items.SetCount(1); items[0].fItem = item; items[0].fOptions.fTint1.Set(tint1.getRed(), tint1.getGreen(), tint1.getBlue(), 1.f); items[0].fOptions.fTint2.Set(tint2.getRed(), tint2.getGreen(), tint2.getBlue(), 1.f); plClothingMgr::GetClothingMgr()->AddItemsToCloset(items); } } ///////////////////////////////////////////////////////////////////////////// // // Function : GetUniqueMeshList // PARAMETERS : clothing_type - the type of clothing to get // // PURPOSE : Return a list of unique clothing items (each has a different mesh) // : that belong to the specific type // std::vector cyAvatar::GetUniqueMeshList(Int32 clothing_type) { std::vector retVal; // find the avatar's armature modifier const plArmatureMod *avMod = nil; // we can really only talk to one avatar, so just get the first one (which is probably the only one) if ( fRecvr.Count() > 0 && fRecvr[0] != nil ) { plSceneObject *so = plSceneObject::ConvertNoRef(fRecvr[0]->GetObjectPtr()); if (so != nil) { avMod = (plArmatureMod*)so->GetModifierByType(plArmatureMod::Index()); if ( avMod ) { // Get all the clothes that we can wear hsTArray clothingList; plClothingMgr::GetClothingMgr()->GetItemsByGroup(avMod->GetClothingOutfit()->fGroup, clothingList); plClothingMgr::GetClothingMgr()->FilterUniqueMeshes(clothingList); // filter all redundant meshes int numItems = clothingList.GetCount(); // create the string list to send to python... as a python object int i; for ( i=0; ifType == clothing_type ) { // add this event record to the main event list (lists within a list) // create list PyObject* clothingItem = PyList_New(5); // [0] = clothing name PyList_SetItem(clothingItem, 0, PyString_FromString(item->GetName())); // [1] = clothing type PyList_SetItem(clothingItem, 1, PyInt_FromLong(item->fType)); // [2] = description const char* description = ""; // assume an empty string if ( item->fDescription != nil ) description = item->fDescription; PyList_SetItem(clothingItem, 2, PyString_FromString(description)); // [3] = ptImage of icon if ( item->fThumbnail != nil ) // create a ptImage PyList_SetItem(clothingItem, 3, pyImage::New(item->fThumbnail->GetKey())); else PyList_SetItem(clothingItem, 3, PyInt_FromLong(0)); // [4] = fCustomText const char* custom = ""; // assume an empty string if ( item->fCustomText != nil ) custom = item->fCustomText; PyList_SetItem(clothingItem, 4, PyString_FromString(custom)); retVal.push_back(clothingItem); } } } } } return retVal; } ///////////////////////////////////////////////////////////////////////////// // // Function : GetAllWithSameMesh // PARAMETERS : clothing_name - the name of the mesh to get the textures of // // PURPOSE : Return a list of clothing items that have the same mesh as // : the item passed in // std::vector cyAvatar::GetAllWithSameMesh(const char* clothing_name) { std::vector retVal; // find the avatar's armature modifier const plArmatureMod *avMod = nil; // we can really only talk to one avatar, so just get the first one (which is probably the only one) if ( fRecvr.Count() > 0 && fRecvr[0] != nil ) { plSceneObject *so = plSceneObject::ConvertNoRef(fRecvr[0]->GetObjectPtr()); if (so != nil) { avMod = (plArmatureMod*)so->GetModifierByType(plArmatureMod::Index()); if ( avMod ) { // Get all clothes with the same mesh as the one passed in hsTArray clothingList; plClothingMgr::GetClothingMgr()->GetAllWithSameMesh(plClothingMgr::GetClothingMgr()->FindItemByName((char*)clothing_name), clothingList); int numItems = clothingList.GetCount(); // create the string list to send to python... as a python object int i; for ( i=0; iGetName())); // [1] = clothing type PyList_SetItem(clothingItem, 1, PyInt_FromLong(item->fType)); // [2] = description const char* description = ""; // assume an empty string if ( item->fDescription != nil ) description = item->fDescription; PyList_SetItem(clothingItem, 2, PyString_FromString(description)); // [3] = ptImage of icon if ( item->fThumbnail != nil ) // create a ptImage PyList_SetItem(clothingItem, 3, pyImage::New(item->fThumbnail->GetKey())); else PyList_SetItem(clothingItem, 3, PyInt_FromLong(0)); // [4] = fCustomText const char* custom = ""; // assume an empty string if ( item->fCustomText != nil ) custom = item->fCustomText; PyList_SetItem(clothingItem, 4, PyString_FromString(custom)); retVal.push_back(clothingItem); } } } } return retVal; } ///////////////////////////////////////////////////////////////////////////// // // Function : GetMatchingClothingItem // PARAMETERS : // // PURPOSE : Return the clothing item that matches this one // : If no match then returns the number 0 // PyObject* cyAvatar::GetMatchingClothingItem(const char* clothing_name) { // Get all the clothes that we can wear hsTArray clothingList; plClothingItem* match = plClothingMgr::GetClothingMgr()->GetLRMatch(plClothingMgr::GetClothingMgr()->FindItemByName((char*)clothing_name)); if ( match ) { // create list PyObject* clothingItem = PyList_New(5); // [0] = clothing name PyList_SetItem(clothingItem, 0, PyString_FromString(match->GetName())); // [1] = clothing type PyList_SetItem(clothingItem, 1, PyInt_FromLong(match->fType)); // [2] = description const char* description = ""; // assume an empty string if ( match->fDescription != nil ) description = match->fDescription; PyList_SetItem(clothingItem, 2, PyString_FromString(description)); // [3] = ptImage of icon if ( match->fThumbnail != nil ) // create a ptImage PyList_SetItem(clothingItem, 3, pyImage::New(match->fThumbnail->GetKey())); else PyList_SetItem(clothingItem, 3, PyInt_FromLong(0)); // [4] = fCustomText const char* custom = ""; // assume an empty string if ( match->fCustomText != nil ) custom = match->fCustomText; PyList_SetItem(clothingItem, 4, PyString_FromString(custom)); return clothingItem; } else return PyInt_FromLong(0); } ///////////////////////////////////////////////////////////////////////////// // // Function : WearClothingItem // PARAMETERS : // // PURPOSE : Wear a particular piece of clothing based on name of clothing item // : returns 0, if clothing item was not found // hsBool cyAvatar::WearClothingItem(const char* clothing_name) { return WearClothingItemU(clothing_name,true); } ///////////////////////////////////////////////////////////////////////////// // // Function : RemoveClothingItem // PARAMETERS : // // PURPOSE : Wear a particular piece of clothing based on name of clothing item // : returns false, if clothing item was not found // hsBool cyAvatar::RemoveClothingItem(const char* clothing_name) { return RemoveClothingItemU(clothing_name,true); } ///////////////////////////////////////////////////////////////////////////// // // Function : TintClothingItem // PARAMETERS : // // PURPOSE : Tint a clothing item, i.e. change the color of it // hsBool cyAvatar::TintClothingItem(const char* clothing_name, pyColor& tint) { return TintClothingItemU(clothing_name,tint,true); } ///////////////////////////////////////////////////////////////////////////// // // Function : TintClothingItemLayer // PARAMETERS : clothing_name - name of the clothing item to change the color of // : tint - what color to change it to // : layer - which layer to change (1 or 2) // // PURPOSE : Tint a clothing item, i.e. change the color of it // hsBool cyAvatar::TintClothingItemLayer(const char* clothing_name, pyColor& tint, UInt8 layer) { return TintClothingItemLayerU(clothing_name,tint,layer,true); } ///////////////////////////////////////////////////////////////////////////// // // Function : WearClothingItem // PARAMETERS : --- with update flag // // PURPOSE : Wear a particular piece of clothing based on name of clothing item // : returns 0, if clothing item was not found // hsBool cyAvatar::WearClothingItemU(const char* clothing_name, hsBool update) { const plArmatureMod *avMod = nil; // we can really only talk to one avatar, so just get the first one (which is probably the only one) if ( fRecvr.Count() > 0 && fRecvr[0] != nil ) { plSceneObject *so = plSceneObject::ConvertNoRef(fRecvr[0]->GetObjectPtr()); if (so != nil) { avMod = (plArmatureMod*)so->GetModifierByType(plArmatureMod::Index()); plClothingItem *item = plClothingMgr::GetClothingMgr()->FindItemByName((char*)clothing_name); if (avMod && item) { if ( fNetForce ) avMod->GetClothingOutfit()->AddItem(item, update, true, true); else avMod->GetClothingOutfit()->AddItem(item, update); return true; } } } return false; } ///////////////////////////////////////////////////////////////////////////// // // Function : RemoveClothingItemU // PARAMETERS : --- with update flag // // PURPOSE : Wear a particular piece of clothing based on name of clothing item // : returns false, if clothing item was not found // hsBool cyAvatar::RemoveClothingItemU(const char* clothing_name, hsBool update) { const plArmatureMod *avMod = nil; // we can really only talk to one avatar, so just get the first one (which is probably the only one) if ( fRecvr.Count() > 0 && fRecvr[0] != nil ) { plSceneObject *so = plSceneObject::ConvertNoRef(fRecvr[0]->GetObjectPtr()); if (so != nil) { avMod = (plArmatureMod*)so->GetModifierByType(plArmatureMod::Index()); plClothingItem *item = plClothingMgr::GetClothingMgr()->FindItemByName((char*)clothing_name); if (avMod && item) { if ( fNetForce ) avMod->GetClothingOutfit()->RemoveItem(item,update,true); else avMod->GetClothingOutfit()->RemoveItem(item,update); return true; } } } return false; } ///////////////////////////////////////////////////////////////////////////// // // Function : TintClothingItemU // PARAMETERS : --- with update flag // // PURPOSE : Tint a clothing item, i.e. change the color of it // hsBool cyAvatar::TintClothingItemU(const char* clothing_name, pyColor& tint, hsBool update) { const plArmatureMod *avMod = nil; // we can really only talk to one avatar, so just get the first one (which is probably the only one) if ( fRecvr.Count() > 0 && fRecvr[0] != nil ) { plSceneObject *so = plSceneObject::ConvertNoRef(fRecvr[0]->GetObjectPtr()); if (so != nil) { avMod = (plArmatureMod*)so->GetModifierByType(plArmatureMod::Index()); plClothingItem *item = plClothingMgr::GetClothingMgr()->FindItemByName((char*)clothing_name); if (avMod && item) { avMod->GetClothingOutfit()->TintItem(item, tint.getRed(),tint.getGreen(),tint.getBlue(),update,true,fNetForce,true,plClothingElement::kLayerTint1); return true; } } } return false; } ///////////////////////////////////////////////////////////////////////////// // // Function : TintClothingItemLayer // PARAMETERS : clothing_name - name of the clothing item to change the color of // : tint - what color to change it to // : layer - which layer to change (1 or 2) // // PURPOSE : Tint a clothing item, i.e. change the color of it // hsBool cyAvatar::TintClothingItemLayerU(const char* clothing_name, pyColor& tint, UInt8 layer, hsBool update) { const plArmatureMod *avMod = nil; // we can really only talk to one avatar, so just get the first one (which is probably the only one) if ( fRecvr.Count() > 0 && fRecvr[0] != nil ) { plSceneObject *so = plSceneObject::ConvertNoRef(fRecvr[0]->GetObjectPtr()); if (so != nil) { avMod = (plArmatureMod*)so->GetModifierByType(plArmatureMod::Index()); plClothingItem *item = plClothingMgr::GetClothingMgr()->FindItemByName((char*)clothing_name); if (avMod && item) { // Convert Python layer number to clothing code... if (layer == 2) layer = plClothingElement::kLayerTint2; else layer = plClothingElement::kLayerTint1; avMod->GetClothingOutfit()->TintItem(item, tint.getRed(),tint.getGreen(),tint.getBlue(),update,true,fNetForce,true,layer); return true; } } } return false; } ///////////////////////////////////////////////////////////////////////////// // // Function : GetClothingItemParameterString // PARAMETERS : // // PURPOSE : Get the custom parameter string for a clothing item // const char* cyAvatar::GetClothingItemParameterString(const char* clothing_name) { const plArmatureMod *avMod = nil; // we can really only talk to one avatar, so just get the first one (which is probably the only one) if ( fRecvr.Count() > 0 && fRecvr[0] != nil ) { plSceneObject *so = plSceneObject::ConvertNoRef(fRecvr[0]->GetObjectPtr()); if (so != nil) { avMod = (plArmatureMod*)so->GetModifierByType(plArmatureMod::Index()); plClothingItem *item = plClothingMgr::GetClothingMgr()->FindItemByName((char*)clothing_name); if (avMod && item) { if ( item->fCustomText != nil ) return item->fCustomText; else return ""; } } } return ""; } ///////////////////////////////////////////////////////////////////////////// // // Function : GetTintClothingItem // PARAMETERS : // // PURPOSE : Get the tint a clothing item, i.e. change the color of it // PyObject* cyAvatar::GetTintClothingItem(const char* clothing_name) { return GetTintClothingItemL(clothing_name,1); } ///////////////////////////////////////////////////////////////////////////// // // Function : GetTintClothingItem // PARAMETERS : // // PURPOSE : Get the tint a clothing item, i.e. change the color of it // PyObject* cyAvatar::GetTintClothingItemL(const char* clothing_name, UInt8 layer) { const plArmatureMod *avMod = nil; // we can really only talk to one avatar, so just get the first one (which is probably the only one) if ( fRecvr.Count() > 0 && fRecvr[0] != nil ) { plSceneObject *so = plSceneObject::ConvertNoRef(fRecvr[0]->GetObjectPtr()); if (so != nil) { avMod = (plArmatureMod*)so->GetModifierByType(plArmatureMod::Index()); plClothingItem *item = plClothingMgr::GetClothingMgr()->FindItemByName((char*)clothing_name); if (avMod && item) { // Convert Python layer number to clothing code... if (layer == 2) layer = plClothingElement::kLayerTint2; else layer = plClothingElement::kLayerTint1; hsColorRGBA tint = avMod->GetClothingOutfit()->GetItemTint(item,layer); return pyColor::New(tint); } } } char errmsg[256]; sprintf(errmsg,"Cannot find clothing item %d to find out what tint it is",clothing_name); PyErr_SetString(PyExc_KeyError, errmsg); // returning nil means an error occurred return nil; } ///////////////////////////////////////////////////////////////////////////// // // Function : TintSkin // PARAMETERS : // // PURPOSE : Tint the skin of the player's avatar // void cyAvatar::TintSkin(pyColor& tint) { TintSkinU(tint,true); } ///////////////////////////////////////////////////////////////////////////// // // Function : TintSkinU // PARAMETERS : // // PURPOSE : Tint the skin of the player's avatar with optional update flag // void cyAvatar::TintSkinU(pyColor& tint, hsBool update) { const plArmatureMod *avMod = nil; // we can really only talk to one avatar, so just get the first one (which is probably the only one) if ( fRecvr.Count() > 0 && fRecvr[0] != nil ) { plSceneObject *so = plSceneObject::ConvertNoRef(fRecvr[0]->GetObjectPtr()); if (so != nil) { avMod = (plArmatureMod*)so->GetModifierByType(plArmatureMod::Index()); avMod->GetClothingOutfit()->TintSkin(tint.getRed(),tint.getGreen(),tint.getBlue(),update,true); } } } ///////////////////////////////////////////////////////////////////////////// // // Function : GetTintSkin // PARAMETERS : // // PURPOSE : Get the tint of the skin of the player's avatar // PyObject* cyAvatar::GetTintSkin() { const plArmatureMod *avMod = nil; // we can really only talk to one avatar, so just get the first one (which is probably the only one) if ( fRecvr.Count() > 0 && fRecvr[0] != nil ) { plSceneObject *so = plSceneObject::ConvertNoRef(fRecvr[0]->GetObjectPtr()); if (so != nil) { avMod = (plArmatureMod*)so->GetModifierByType(plArmatureMod::Index()); hsColorRGBA tint = avMod->GetClothingOutfit()->fSkinTint; // now create the ptColor Python object return pyColor::New(tint); } } char errmsg[256]; sprintf(errmsg,"Cannot find the skin of the player. Whatever that means!"); PyErr_SetString(PyExc_KeyError, errmsg); // returning nil means an error occurred return nil; } plMorphSequence* cyAvatar::LocalMorphSequence() { plArmatureMod *avMod = plAvatarMgr::GetInstance()->GetLocalAvatar(); if (!avMod) return nil; const plSceneObject *so = avMod->GetClothingSO(0); // grabbing the high LOD node if (!so) return nil; const plModifier* constSeq = nil; int i; for (i = 0; i < so->GetNumModifiers(); i++) { constSeq = so->GetModifier(i); if (constSeq && plMorphSequence::ConvertNoRef(constSeq)) { return (plMorphSequence*)constSeq; // safe cast, we've already checked type (plus we're const_cast'ing). } } return nil; } ///////////////////////////////////////////////////////////////////////////// // // Function : SetMorph // PARAMETERS : clothing_name - the name of the clothing to morph // : layer - the layer to affect // : value - what the new value should be (clipped between -1 and 1) // // PURPOSE : Set the morph value of a specific layer of clothing // void cyAvatar::SetMorph(const char* clothing_name, UInt8 layer, float value) { plClothingItem *item = plClothingMgr::GetClothingMgr()->FindItemByName(clothing_name); if( !item ) { PyErr_SetString(PyExc_KeyError, "Item not found"); return; } float wgtPlus; float wgtMinus; if(value > 1.0) value = 1.0; if(value < -1.0) value = -1.0; if (value > 0) { wgtPlus = value; wgtMinus = 0; } else { wgtMinus = -value; wgtPlus = 0; } if ( fRecvr.Count() > 0 && fRecvr[0] != nil ) { plSceneObject *so = plSceneObject::ConvertNoRef(fRecvr[0]->GetObjectPtr()); if (so != nil) { const plArmatureMod *avMod = (plArmatureMod*)so->GetModifierByType(plArmatureMod::Index()); if (avMod && avMod->GetClothingOutfit()) { avMod->GetClothingOutfit()->MorphItem(item, layer, 0, wgtPlus, true); avMod->GetClothingOutfit()->MorphItem(item, layer, 1, wgtMinus, true); } } } } ///////////////////////////////////////////////////////////////////////////// // // Function : GetMorph // PARAMETERS : clothing_name - the name of the clothing to get the value from // : layer - the layer to get the value from // // PURPOSE : Returns the current morph value of the specific layer of clothing // float cyAvatar::GetMorph(const char* clothing_name, UInt8 layer) { plMorphSequence* seq = LocalMorphSequence(); if( !seq ) { PyErr_SetString(PyExc_KeyError, "Sequence not found"); return 0; } plClothingItem *item = plClothingMgr::GetClothingMgr()->FindItemByName(clothing_name); if( !item ) { PyErr_SetString(PyExc_KeyError, "Item not found"); return 0; } plKey meshKey = item->fMeshes[0]->GetKey(); if (layer >= seq->GetNumLayers(meshKey)) { PyErr_SetString(PyExc_KeyError, "Layer index too high"); return 0; } float wgtPlus; float wgtMinus; wgtPlus = seq->GetWeight(layer,0,meshKey); wgtMinus = seq->GetWeight(layer,1,meshKey); if (wgtPlus > 0) return wgtPlus; else return -wgtMinus; } ///////////////////////////////////////////////////////////////////////////// // // Function : SetSkinBlend // PARAMETERS : layer - the layer to affect // : value - what the new value should be (clipped between 0 and 1) // // PURPOSE : Set the skin blend for the specified layer // void cyAvatar::SetSkinBlend(UInt8 layer, float value) { if (value < 0.0) value = 0.0; if (value > 1.0) value = 1.0; plArmatureMod *avMod = plAvatarMgr::GetInstance()->GetLocalAvatar(); if (avMod) { avMod->GetClothingOutfit()->SetSkinBlend(value, (int)layer + plClothingElement::kLayerSkinBlend1 - 1); } } ///////////////////////////////////////////////////////////////////////////// // // Function : GetSkinBlend // PARAMETERS : layer - the layer to get the blend for // // PURPOSE : Returns the current layer's skin blend // float cyAvatar::GetSkinBlend(UInt8 layer) { plArmatureMod *avMod = plAvatarMgr::GetInstance()->GetLocalAvatar(); if (avMod) { return avMod->GetClothingOutfit()->GetSkinBlend((int)layer + plClothingElement::kLayerSkinBlend1 - 1); } return 0; } ///////////////////////////////////////////////////////////////////////////// // // Function : SaveClothing // PARAMETERS : // // PURPOSE : Saves the current clothing to the vault (including morphs) // void cyAvatar::SaveClothing() { plArmatureMod *avMod = plAvatarMgr::GetInstance()->GetLocalAvatar(); if (avMod) avMod->GetClothingOutfit()->SaveCustomizations(); } ///////////////////////////////////////////////////////////////////////////// // // Function : EnterSubWorld // PARAMETERS : object - a sceneobject that is in the subworld // // PURPOSE : Place the Avatar into the subworld of the sceneobject specified // void cyAvatar::EnterSubWorld(pySceneObject& object) { // make sure that there is atleast one avatar scene object attached (should be) if ( fRecvr.Count() > 0) { // find the armature modifier plArmatureMod* avatar = (plArmatureMod*)IFindArmatureMod((plKey)fRecvr[0]); if(avatar) { // get the sceneobject that we will use to find the subworld plKey SOkey = object.getObjKey(); if ( SOkey ) { plSceneObject *SO = plSceneObject::ConvertNoRef(SOkey->ObjectIsLoaded()); if(SO) { plKey subWorldKey = SOkey; plKey physKey = avatar->GetKey(); plKey nilKey; // sorry plSubWorldMsg *swMsg = TRACKED_NEW plSubWorldMsg(nilKey, physKey, subWorldKey); swMsg->Send(); } } } } } ///////////////////////////////////////////////////////////////////////////// // // Function : ExitSubWorld // PARAMETERS : (none) // // PURPOSE : Exit the avatar from the subworld, back into the ... world // void cyAvatar::ExitSubWorld() { // make sure that there is atleast one avatar scene object attached (should be) if ( fRecvr.Count() > 0) { // find the armature modifier plArmatureMod* avatar = (plArmatureMod*)IFindArmatureMod((plKey)fRecvr[0]); if(avatar) { plKey subWorldKey; // we're going to the nil subworld plKey physKey = avatar->GetKey(); plKey nilKey; // sorry plSubWorldMsg *swMsg = TRACKED_NEW plSubWorldMsg(nilKey, physKey, subWorldKey); swMsg->Send(); } } } ///////////////////////////////////////////////////////////////////////////// // // Function : PlaySimpleAnimation // PARAMETERS : object - a sceneobject that is in the subworld // // PURPOSE : Place the Avatar into the subworld of the sceneobject specified // void cyAvatar::PlaySimpleAnimation(const char* animName) { // make sure that there is atleast one avatar scene object attached (should be) if ( fRecvr.Count() > 0) { // find the armature modifier plArmatureMod* avatar = (plArmatureMod*)IFindArmatureMod((plKey)fRecvr[0]); if(avatar) { avatar->PlaySimpleAnim(animName); } } } ///////////////////////////////////////////////////////////////////////////// // // Function : ChangeAvatar // PARAMETERS : gender name - is a string of the name of the gender to go to // // PURPOSE : Change the local avatar's gender. // // Valid genders: // Male // Female // void cyAvatar::ChangeAvatar(const char* genderName) { #ifndef PLASMA_EXTERNAL_RELEASE plClothingMgr::ChangeAvatar((char*)genderName); wchar wStr[MAX_PATH]; StrToUnicode(wStr, genderName, arrsize(wStr)); RelVaultNode * rvnPlr = VaultGetPlayerNodeIncRef(); if (rvnPlr) { VaultPlayerNode plr(rvnPlr); plr.SetAvatarShapeName(wStr); rvnPlr->DecRef(); } #endif } ///////////////////////////////////////////////////////////////////////////// // // Function : ChangePlayerName // PARAMETERS : name - is a string of the new name for the player // // PURPOSE : Change the local player's avatar name // void cyAvatar::ChangePlayerName(const char* playerName) { wchar wStr[MAX_PATH]; StrToUnicode(wStr, playerName, arrsize(wStr)); RelVaultNode * rvnPlr = VaultGetPlayerNodeIncRef(); if (rvnPlr) { VaultPlayerNode plr(rvnPlr); plr.SetPlayerName(wStr); rvnPlr->DecRef(); } } ///////////////////////////////////////////////////////////////////////////// // // Function : Emote // PARAMETERS : emoteName - name of the emote to play on the avatar // // PURPOSE : plays an emote on a the local avatar (net propagated) // bool cyAvatar::Emote(const char* emoteName) { // can we find an emote of this name? plArmatureMod *avatar = plAvatarMgr::GetInstance()->GetLocalAvatar(); return AvatarEmote(avatar, emoteName); } ///////////////////////////////////////////////////////////////////////////// // // Function : Sit // PARAMETERS : none // // PURPOSE : Makes the avatar sit down on the ground where they are. // The avatar will automatically stand when the user tries to move. // bool cyAvatar::Sit() { return IEnterGenericMode("SitDownGround", "SitIdleGround", "SitStandGround", true, plAGAnim::kBodyLower, plAvBrainGeneric::kSitOnGround); } ///////////////////////////////////////////////////////////////////////////// // // Function : EnterKiMode // PARAMETERS : none // // PURPOSE : Makes the avatar appear to be using the ki. // bool cyAvatar::EnterKiMode() { return IEnterGenericMode("KiBegin", "KiUse", "KiEnd", false, plAGAnim::kBodyFull); } ///////////////////////////////////////////////////////////////////////////// // // Function : ExitKiMode // PARAMETERS : none // // PURPOSE : Makes the avatar stop appearing to use the ki. // May cause problems if EnterKiMode() was not called earlier. // bool cyAvatar::ExitKiMode() { return IExitTopmostGenericMode(); } ///////////////////////////////////////////////////////////////////////////// // // Function : EnterAFKMode // PARAMETERS : none // // PURPOSE : Tell the avatar to enter the AFK mode (sitting, head down) // bool cyAvatar::EnterAFKMode() { return IEnterGenericMode("AFKEnter", "AFKIdle", "AFKExit", true, plAGAnim::kBodyFull, plAvBrainGeneric::kAFK); } ///////////////////////////////////////////////////////////////////////////// // // Function : ExitAFKMode // PARAMETERS : none // // PURPOSE : Tell the avatar to exit the AFK mode // May cause problems if EnterKiMode() was not called earlier. // bool cyAvatar::ExitAFKMode() { return IExitTopmostGenericMode(); } ///////////////////////////////////////////////////////////////////////////// // // Function : EnterPBMode // PARAMETERS : none // // PURPOSE : Enter the personal book mode...stay until further notice. // bool cyAvatar::EnterPBMode() { return IEnterGenericMode("PersonalBookEnter", "PersonalBookIdle", "PersonalBookExit", false, plAGAnim::kBodyFull); } ///////////////////////////////////////////////////////////////////////////// // // Function : ExitPBMode // PARAMETERS : none // // PURPOSE : Leave the personal book mode. Currently leaves any mode; will become // : more specific in future version // bool cyAvatar::ExitPBMode() { return IExitTopmostGenericMode(); } int cyAvatar::GetCurrentMode() { // make sure that there is atleast one avatar scene object attached (should be) if ( fRecvr.Count() > 0) { // find the armature modifier plArmatureMod* avatar = (plArmatureMod*)IFindArmatureMod((plKey)fRecvr[0]); if(avatar) { return avatar->GetCurrentGenericType(); } } return plAvBrainGeneric::kNonGeneric; } ///////////////////////////////////////////////////////////////////////////// // // Function : disable movement controls // PARAMETERS : // // PURPOSE : something tells me python shouldn't do this this way // void cyAvatar::DisableMovementControls() { plArmatureMod *avatar = plAvatarMgr::GetInstance()->GetLocalAvatar(); if (avatar) { if (!avatar->IsInputSuspended()) avatar->SuspendInput(); } } void cyAvatar::EnableMovementControls() { plArmatureMod *avatar = plAvatarMgr::GetInstance()->GetLocalAvatar(); if (avatar) { if (avatar->IsInputSuspended()) avatar->ResumeInput(); } } void cyAvatar::DisableMouseMovement() { plAvatarInputInterface::GetInstance()->SuspendMouseMovement(); } void cyAvatar::EnableMouseMovement() { plAvatarInputInterface::GetInstance()->EnableMouseMovement(); } void cyAvatar::EnableAvatarJump() { plAvatarInputInterface::GetInstance()->EnableJump(true); } void cyAvatar::DisableAvatarJump() { plAvatarInputInterface::GetInstance()->EnableJump(false); } void cyAvatar::EnableForwardMovement() { plAvatarInputInterface::GetInstance()->EnableForwardMovement(true); } void cyAvatar::DisableForwardMovement() { plAvatarInputInterface::GetInstance()->EnableForwardMovement(false); } bool cyAvatar::LocalAvatarRunKeyDown() { plArmatureMod *avMod = plAvatarMgr::GetInstance()->GetLocalAvatar(); if (avMod) return avMod->FastKeyDown(); return false; } bool cyAvatar::LocalAvatarIsMoving() { plArmatureMod *avMod = plAvatarMgr::GetInstance()->GetLocalAvatar(); if (avMod) return avMod->ForwardKeyDown() || avMod->BackwardKeyDown() || avMod->StrafeRightKeyDown() || avMod->StrafeLeftKeyDown() || avMod->TurnRightKeyDown() || avMod->TurnLeftKeyDown() || avMod->JumpKeyDown(); return false; } void cyAvatar::SetMouseTurnSensitivity(hsScalar val) { plArmatureMod::SetMouseTurnSensitivity(val); } hsScalar cyAvatar::GetMouseTurnSensitivity() { return plArmatureMod::GetMouseTurnSensitivity(); } void cyAvatar::SpawnNext() { static int whichSpawn = 0; plAvatarMgr *mgr = plAvatarMgr::GetInstance(); int max = mgr->NumSpawnPoints(); whichSpawn = ++whichSpawn < max ? whichSpawn : 0; plArmatureMod *avatar = plAvatarMgr::GetInstance()->GetLocalAvatar(); if(avatar) { double fakeTime = 0.0f; avatar->SpawnAt(whichSpawn, fakeTime); } } ///////////////////////////////////////////////////////////////////////////// // // Function : RegisterForBehaviorNotify() // PARAMETERS : none // // PURPOSE : To register for notifies from the avatar for any kind of behavior notify // void cyAvatar::RegisterForBehaviorNotify(pyKey &selfKey) { // make sure that there is atleast one avatar scene object attached (should be) if ( fRecvr.Count() > 0) { // find the armature modifier plArmatureMod* avatar = (plArmatureMod*)IFindArmatureMod((plKey)fRecvr[0]); if(avatar) { avatar->RegisterForBehaviorNotify(selfKey.getKey()); } } } ///////////////////////////////////////////////////////////////////////////// // // Function : UnRegisterForBehaviorNotify() // PARAMETERS : none // // PURPOSE : To remove the registeration for notifies from the avatar // void cyAvatar::UnRegisterForBehaviorNotify(pyKey &selfKey) { // make sure that there is atleast one avatar scene object attached (should be) if ( fRecvr.Count() > 0) { // find the armature modifier plArmatureMod* avatar = (plArmatureMod*)IFindArmatureMod((plKey)fRecvr[0]); if(avatar) { avatar->UnRegisterForBehaviorNotify(selfKey.getKey()); } } } ///////////////////////////////////////////////////////////////////////////// // // Function : IEnterGenericMode // PARAMETERS : none // // PURPOSE : Three-stage multistage animations (sit down, sit, get up) are really common. // : This does the basic setup. // bool IEnterGenericMode(const char *enterAnim, const char *idleAnim, const char *exitAnim, bool autoExit, plAGAnim::BodyUsage bodyUsage, plAvBrainGeneric::BrainType type /* = kGeneric */) { plArmatureMod *avatar = plAvatarMgr::GetInstance()->GetLocalAvatar(); return PushSimpleMultiStage(avatar, enterAnim, idleAnim, exitAnim, true, autoExit, bodyUsage, type); } ///////////////////////////////////////////////////////////////////////////// // // Function : IExitTopmostGenericMode // PARAMETERS : none // // PURPOSE : Exits whatever multistage animation you're in. We currently don't discriminate; // : that will be added later. // bool IExitTopmostGenericMode() { plArmatureMod *avatar = plAvatarMgr::GetInstance()->GetLocalAvatar(); plAvBrainGenericMsg* pMsg = TRACKED_NEW plAvBrainGenericMsg(nil, avatar->GetKey(), plAvBrainGenericMsg::kGotoStage, 2, false, 0.0, false, false, 0.0); pMsg->SetBCastFlag(plMessage::kNetForce | plMessage::kNetPropagate); plgDispatch::MsgSend( pMsg ); return true; } ///////////////////////////////////////////////////////////////////////////// // // Function : IsCurrentBrainHuman // PARAMETERS : none // // PURPOSE : Returns whether the top most brain is a human brain // hsBool cyAvatar::IsCurrentBrainHuman() { plArmatureMod *avatar = plAvatarMgr::GetInstance()->GetLocalAvatar(); if (avatar) { plArmatureBrain *brain = avatar->GetCurrentBrain(); plAvBrainHuman *human = plAvBrainHuman::ConvertNoRef(brain); if (human) return true; } return false; }