|
|
|
/*==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 <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
Additional permissions under GNU GPL version 3 section 7
|
|
|
|
|
|
|
|
If you modify this Program, or any covered work, by linking or
|
|
|
|
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
|
|
|
|
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
|
|
|
|
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
|
|
|
|
(or a modified version of those libraries),
|
|
|
|
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
|
|
|
|
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
|
|
|
|
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
|
|
|
|
licensors of this Program grant you additional
|
|
|
|
permission to convey the resulting work. Corresponding Source for a
|
|
|
|
non-source form of such a combination shall include the source code for
|
|
|
|
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
|
|
|
|
work.
|
|
|
|
|
|
|
|
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 "cyMisc.h"
|
|
|
|
|
|
|
|
#include "plgDispatch.h"
|
|
|
|
#include "hsResMgr.h"
|
|
|
|
#include "plResMgr/plKeyFinder.h"
|
|
|
|
|
|
|
|
#include "pnKeyedObject/plKey.h"
|
|
|
|
#include "pnKeyedObject/plFixedKey.h"
|
|
|
|
#include "plMessage/plLinkToAgeMsg.h"
|
|
|
|
#include "plMessage/plConsoleMsg.h"
|
|
|
|
#include "plMessage/plAnimCmdMsg.h"
|
|
|
|
#include "plMessage/plExcludeRegionMsg.h"
|
|
|
|
#include "plMessage/plInputEventMsg.h"
|
|
|
|
#include "plMessage/plInputIfaceMgrMsg.h"
|
|
|
|
#include "pnMessage/plCmdIfaceModMsg.h"
|
|
|
|
#include "pnMessage/plAttachMsg.h"
|
|
|
|
#include "plMessage/plTimerCallbackMsg.h"
|
|
|
|
#include "plMessage/plNetVoiceListMsg.h"
|
|
|
|
#include "pnMessage/plClientMsg.h"
|
|
|
|
#include "pnMessage/plCameraMsg.h"
|
|
|
|
#include "pnTimer/plTimerCallbackManager.h"
|
|
|
|
#include "plVault/plVault.h"
|
|
|
|
#include "pnNetCommon/plCreatableUuid.h"
|
|
|
|
#include "plNetClient/plNetClientMgr.h"
|
|
|
|
#include "plNetClient/plNetLinkingMgr.h"
|
|
|
|
#include "plNetTransport/plNetTransport.h"
|
|
|
|
#include "plNetTransport/plNetTransportMember.h"
|
|
|
|
#include "plResMgr/plKeyFinder.h"
|
|
|
|
#include "plAvatar/plAvatarMgr.h"
|
|
|
|
#include "plAvatar/plMultistageBehMod.h"
|
|
|
|
#include "plAvatar/plAvBrainCritter.h"
|
|
|
|
#include "pyCritterBrain.h"
|
|
|
|
#include "cyPythonInterface.h"
|
|
|
|
#include "pyKey.h"
|
|
|
|
#include "pySceneObject.h"
|
|
|
|
#include "pyPlayer.h"
|
|
|
|
#include "pyImage.h"
|
|
|
|
#include "pyDniCoordinates.h"
|
|
|
|
#include "pyDniInfoSource.h"
|
|
|
|
#include "pyColor.h"
|
|
|
|
#include "pyNetLinkingMgr.h"
|
|
|
|
#include "pyAgeInfoStruct.h"
|
|
|
|
#include "pyAgeLinkStruct.h"
|
|
|
|
#include "pyAlarm.h"
|
|
|
|
#include "pfMessage/pfKIMsg.h"
|
|
|
|
#include "plNetMessage/plNetMessage.h"
|
|
|
|
#include "pfCamera/plVirtualCamNeu.h"
|
|
|
|
#include "plPipeline/plDynamicEnvMap.h"
|
|
|
|
|
|
|
|
#include "pfGameGUIMgr/pfGameGUIMgr.h"
|
|
|
|
#include "pfGameGUIMgr/pfGUIDialogMod.h"
|
|
|
|
#include "pyGUIDialog.h"
|
|
|
|
#include "pnSceneObject/plSceneObject.h"
|
|
|
|
#include "pnSceneObject/plCoordinateInterface.h"
|
|
|
|
|
|
|
|
#include "plMessage/plCCRMsg.h"
|
|
|
|
#include "plAgeLoader/plAgeLoader.h"
|
|
|
|
|
|
|
|
#include "plResMgr/plLocalization.h"
|
|
|
|
#include "plGLight/plLightInfo.h"
|
|
|
|
|
|
|
|
#include "plInputCore/plAvatarInputInterface.h"
|
|
|
|
#include "plInputCore/plInputDevice.h"
|
|
|
|
|
|
|
|
#include "plVault/plAgeInfoSource.h"
|
|
|
|
|
|
|
|
#include "pfLocalizationMgr/pfLocalizationMgr.h"
|
|
|
|
|
|
|
|
//// Static Class Stuff //////////////////////////////////////////////////////
|
|
|
|
plPipeline* cyMisc::fPipeline = nil;
|
|
|
|
uint32_t cyMisc::fUniqueNumber = 0;
|
|
|
|
|
|
|
|
#ifdef PLASMA_EXTERNAL_RELEASE
|
|
|
|
uint32_t cyMisc::fPythonLoggingLevel = cyMisc::kErrorLevel;
|
|
|
|
#else
|
|
|
|
uint32_t cyMisc::fPythonLoggingLevel = cyMisc::kWarningLevel;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
// static
|
|
|
|
void cyMisc::Update( double secs )
|
|
|
|
{
|
|
|
|
// only update once per 1/2 sec
|
|
|
|
static double lastUpdateTime = 0.0;
|
|
|
|
if ( secs-lastUpdateTime>=0.5 )
|
|
|
|
{
|
|
|
|
lastUpdateTime = secs;
|
|
|
|
pyAlarmMgr::GetInstance()->Update( secs );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Function : Get/SetDebugPrintLevel
|
|
|
|
//
|
|
|
|
// PURPOSE : gets and sets the python debug print level
|
|
|
|
//
|
|
|
|
uint32_t cyMisc::GetPythonLoggingLevel()
|
|
|
|
{
|
|
|
|
return fPythonLoggingLevel;
|
|
|
|
}
|
|
|
|
void cyMisc::SetPythonLoggingLevel(uint32_t new_level)
|
|
|
|
{
|
|
|
|
fPythonLoggingLevel = new_level;
|
|
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Function : Console
|
|
|
|
// PARAMETERS : command - string of console commmand to execute
|
|
|
|
//
|
|
|
|
// PURPOSE : Execute a console command from a python script
|
|
|
|
//
|
|
|
|
void cyMisc::Console(const char* command)
|
|
|
|
{
|
|
|
|
if ( command != nil )
|
|
|
|
{
|
|
|
|
// create message to send to the console
|
|
|
|
plControlEventMsg* pMsg = new plControlEventMsg;
|
|
|
|
pMsg->SetBCastFlag(plMessage::kBCastByType);
|
|
|
|
pMsg->SetControlCode(B_CONTROL_CONSOLE_COMMAND);
|
|
|
|
pMsg->SetControlActivated(true);
|
|
|
|
pMsg->SetCmdString(command);
|
|
|
|
plgDispatch::MsgSend( pMsg ); // whoosh... off it goes
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void cyMisc::ConsoleNet(const char* command, hsBool netForce)
|
|
|
|
{
|
|
|
|
if ( command != nil )
|
|
|
|
{
|
|
|
|
// create message to send to the console
|
|
|
|
plControlEventMsg* pMsg = new plControlEventMsg;
|
|
|
|
pMsg->SetBCastFlag(plMessage::kBCastByType);
|
|
|
|
pMsg->SetBCastFlag(plMessage::kNetPropagate);
|
|
|
|
if ( netForce )
|
|
|
|
pMsg->SetBCastFlag(plMessage::kNetForce);
|
|
|
|
pMsg->SetControlCode(B_CONTROL_CONSOLE_COMMAND);
|
|
|
|
pMsg->SetControlActivated(true);
|
|
|
|
pMsg->SetCmdString(command);
|
|
|
|
plgDispatch::MsgSend( pMsg ); // whoosh... off it goes
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Function : FindSceneObject
|
|
|
|
// PARAMETERS : name - string of name of the sceneobject
|
|
|
|
// : ageName - string of the name of the age to look in
|
|
|
|
//
|
|
|
|
// PURPOSE : Execute a console command from a python script,
|
|
|
|
// optionally propagate over the net
|
|
|
|
//
|
|
|
|
PyObject* cyMisc::FindSceneObject(const plString& name, const char* ageName)
|
|
|
|
{
|
|
|
|
// assume that we won't find the sceneobject (key is equal to nil)
|
|
|
|
plKey key=nil;
|
|
|
|
|
|
|
|
if ( !name.IsEmpty() )
|
|
|
|
{
|
|
|
|
const char* theAge = ageName;
|
|
|
|
if ( ageName[0] == 0 )
|
|
|
|
theAge = nil;
|
|
|
|
key=plKeyFinder::Instance().StupidSearch(theAge,nil,plSceneObject::Index(), name, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( key == nil )
|
|
|
|
{
|
|
|
|
plString errmsg = plString::Format("Sceneobject %s not found",name.c_str());
|
|
|
|
PyErr_SetString(PyExc_NameError, errmsg.c_str());
|
|
|
|
return nil; // return nil cause we errored
|
|
|
|
}
|
|
|
|
return pySceneObject::New(key);
|
|
|
|
}
|
|
|
|
|
|
|
|
PyObject* cyMisc::FindActivator(const plString& name)
|
|
|
|
{
|
|
|
|
plKey key = nil;
|
|
|
|
if (!name.IsEmpty())
|
|
|
|
{
|
|
|
|
std::vector<plKey> keylist;
|
|
|
|
plKeyFinder::Instance().ReallyStupidActivatorSearch(name, keylist);
|
|
|
|
|
|
|
|
if (keylist.size() == 1)
|
|
|
|
key = keylist[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (key == nil)
|
|
|
|
{
|
|
|
|
PYTHON_RETURN_NONE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return pyKey::New(key);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Function : PopUpConsole
|
|
|
|
// PARAMETERS : command - string of console commmand to execute
|
|
|
|
//
|
|
|
|
// PURPOSE : Execute a console command from a python script
|
|
|
|
//
|
|
|
|
void cyMisc::PopUpConsole(const char* command)
|
|
|
|
{
|
|
|
|
if ( command != nil )
|
|
|
|
{
|
|
|
|
// create message to send to the console
|
|
|
|
plControlEventMsg* pMsg1 = new plControlEventMsg;
|
|
|
|
pMsg1->SetBCastFlag(plMessage::kBCastByType);
|
|
|
|
pMsg1->SetControlCode(B_SET_CONSOLE_MODE);
|
|
|
|
pMsg1->SetControlActivated(true);
|
|
|
|
plgDispatch::MsgSend( pMsg1 ); // whoosh... off it goes
|
|
|
|
// create message to send to the console
|
|
|
|
plControlEventMsg* pMsg2 = new plControlEventMsg;
|
|
|
|
pMsg2->SetBCastFlag(plMessage::kBCastByType);
|
|
|
|
pMsg2->SetControlCode(B_CONTROL_CONSOLE_COMMAND);
|
|
|
|
pMsg2->SetControlActivated(true);
|
|
|
|
pMsg2->SetCmdString(command);
|
|
|
|
plgDispatch::MsgSend( pMsg2 ); // whoosh... off it goes
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Function : TimerCallback
|
|
|
|
// PARAMETERS : command - string of console commmand to execute
|
|
|
|
//
|
|
|
|
// PURPOSE : Execute a console command from a python script
|
|
|
|
//
|
|
|
|
void cyMisc::TimerCallback(pyKey& selfkey, float time, uint32_t id)
|
|
|
|
{
|
|
|
|
// setup the message to come back to whoever the pyKey is pointing to
|
|
|
|
plTimerCallbackMsg* pTimerMsg = new plTimerCallbackMsg(selfkey.getKey(),id);
|
|
|
|
plgTimerCallbackMgr::NewTimer( time, pTimerMsg );
|
|
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Function : ClearTimerCallbacks
|
|
|
|
// PARAMETERS : key of object to clear callbacks to
|
|
|
|
//
|
|
|
|
// PURPOSE : clear timer callbacks to a certain key
|
|
|
|
//
|
|
|
|
void cyMisc::ClearTimerCallbacks(pyKey& selfkey)
|
|
|
|
{
|
|
|
|
plgTimerCallbackMgr::CancelCallbacksToKey(selfkey.getKey());
|
|
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Function : AttachObject
|
|
|
|
// PARAMETERS : child object
|
|
|
|
// : to be attached to parent object
|
|
|
|
//
|
|
|
|
// PURPOSE : Attach an object to another object, knowing only their pyKeys
|
|
|
|
//
|
|
|
|
void cyMisc::AttachObject(pyKey& ckey, pyKey& pkey)
|
|
|
|
{
|
|
|
|
plKey childKey = ckey.getKey();
|
|
|
|
plKey parentKey = pkey.getKey();
|
|
|
|
|
|
|
|
// make sure that there was a child ket
|
|
|
|
if ( childKey )
|
|
|
|
{
|
|
|
|
// create the attach message to attach the child
|
|
|
|
plAttachMsg* pMsg = new plAttachMsg(parentKey, childKey->GetObjectPtr(), plRefMsg::kOnRequest);
|
|
|
|
plgDispatch::MsgSend( pMsg );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void cyMisc::AttachObjectSO(pySceneObject& cobj, pySceneObject& pobj)
|
|
|
|
{
|
|
|
|
plKey childKey = cobj.getObjKey();
|
|
|
|
plKey parentKey = pobj.getObjKey();
|
|
|
|
|
|
|
|
// make sure that there was a child ket
|
|
|
|
if ( childKey )
|
|
|
|
{
|
|
|
|
// create the attach message to attach the child
|
|
|
|
plAttachMsg* pMsg = new plAttachMsg(parentKey, childKey->GetObjectPtr(), plRefMsg::kOnRequest);
|
|
|
|
plgDispatch::MsgSend( pMsg );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Function : DetachObject
|
|
|
|
// PARAMETERS : child object
|
|
|
|
// : to be attached to parent object
|
|
|
|
//
|
|
|
|
// PURPOSE : Attach an object to another object, knowing only their pyKeys
|
|
|
|
//
|
|
|
|
void cyMisc::DetachObject(pyKey& ckey, pyKey& pkey)
|
|
|
|
{
|
|
|
|
plKey childKey = ckey.getKey();
|
|
|
|
plKey parentKey = pkey.getKey();
|
|
|
|
|
|
|
|
// make sure that there was a child ket
|
|
|
|
if ( childKey )
|
|
|
|
{
|
|
|
|
// create the attach message to detach the child
|
|
|
|
plAttachMsg* pMsg = new plAttachMsg(parentKey, childKey->GetObjectPtr(), plRefMsg::kOnRemove);
|
|
|
|
plgDispatch::MsgSend( pMsg );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void cyMisc::DetachObjectSO(pySceneObject& cobj, pySceneObject& pobj)
|
|
|
|
{
|
|
|
|
plKey childKey = cobj.getObjKey();
|
|
|
|
plKey parentKey = pobj.getObjKey();
|
|
|
|
|
|
|
|
// make sure that there was a child ket
|
|
|
|
if ( childKey )
|
|
|
|
{
|
|
|
|
// create the attach message to detach the child
|
|
|
|
plAttachMsg* pMsg = new plAttachMsg(parentKey, childKey->GetObjectPtr(), plRefMsg::kOnRemove);
|
|
|
|
plgDispatch::MsgSend( pMsg );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Function : LinkToAge
|
|
|
|
// PARAMETERS :
|
|
|
|
//
|
|
|
|
// PURPOSE : LinkToAge
|
|
|
|
//
|
|
|
|
// STATUS : Depreciated. Use plNetLinkingMgr or pyNetLinkingMgr instead.
|
|
|
|
//
|
|
|
|
|
|
|
|
//void cyMisc::LinkToAge(pyKey &selfkey, const char *AgeName,const char *SpawnPointName)
|
|
|
|
//{
|
|
|
|
// // find the Modifier that called us
|
|
|
|
// hsStatusMessage("PY: LinkToAge\n");
|
|
|
|
// // Ask the Modifier if it was Local or Network
|
|
|
|
// if (selfkey.WasLocalNotify())
|
|
|
|
// {
|
|
|
|
// hsStatusMessage("PY:LOCAL NOTIFY\n");
|
|
|
|
// plNetLinkingMgr::GetInstance()->LinkToPublicAge( AgeName, SpawnPointName );
|
|
|
|
// }
|
|
|
|
// else
|
|
|
|
// {
|
|
|
|
// hsStatusMessage("PY:REMOTE NOTIFY\n");
|
|
|
|
// }
|
|
|
|
//}
|
|
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Function : SetDirtySyncStateServer
|
|
|
|
// PARAMETERS :
|
|
|
|
//
|
|
|
|
// PURPOSE : set the Python modifier to be dirty and asked to be saved out
|
|
|
|
//
|
|
|
|
void cyMisc::SetDirtySyncState(pyKey &selfkey, const char* SDLStateName, uint32_t sendFlags)
|
|
|
|
{
|
|
|
|
selfkey.DirtySynchState(SDLStateName, sendFlags);
|
|
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Function : SetDirtySyncStateClients
|
|
|
|
// PARAMETERS :
|
|
|
|
//
|
|
|
|
// PURPOSE : set the Python modifier to be dirty and asked to be saved out
|
|
|
|
//
|
|
|
|
void cyMisc::SetDirtySyncStateWithClients(pyKey &selfkey, const char* SDLStateName, uint32_t sendFlags)
|
|
|
|
{
|
|
|
|
selfkey.DirtySynchState(SDLStateName, sendFlags|plSynchedObject::kBCastToClients);
|
|
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Function : EnableControlKeyEvents & DisableControlKeyEvents
|
|
|
|
// PARAMETERS : none
|
|
|
|
//
|
|
|
|
// PURPOSE : register and unregister for control key events
|
|
|
|
//
|
|
|
|
void cyMisc::EnableControlKeyEvents(pyKey &selfkey)
|
|
|
|
{
|
|
|
|
selfkey.EnableControlKeyEvents();
|
|
|
|
}
|
|
|
|
|
|
|
|
void cyMisc::DisableControlKeyEvents(pyKey &selfkey)
|
|
|
|
{
|
|
|
|
selfkey.DisableControlKeyEvents();
|
|
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Function : GetClientName
|
|
|
|
// PARAMETERS : avatar key
|
|
|
|
//
|
|
|
|
// PURPOSE : Return the net client (account) name of the player whose avatar
|
|
|
|
// key is provided.
|
|
|
|
//
|
|
|
|
hsBool cyMisc::WasLocallyNotified(pyKey &selfkey)
|
|
|
|
{
|
|
|
|
return selfkey.WasLocalNotify();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Function : GetClientName
|
|
|
|
// PARAMETERS : avatar key
|
|
|
|
//
|
|
|
|
// PURPOSE : Return the net client (account) name of the player whose avatar
|
|
|
|
// key is provided.
|
|
|
|
//
|
|
|
|
plString cyMisc::GetClientName(pyKey &avKey)
|
|
|
|
{
|
|
|
|
return plNetClientMgr::GetInstance()->GetPlayerName(avKey.getKey());
|
|
|
|
}
|
|
|
|
|
|
|
|
PyObject* cyMisc::GetAvatarKeyFromClientID(int clientID)
|
|
|
|
{
|
|
|
|
PyObject* keyObj = NULL;
|
|
|
|
|
|
|
|
if (clientID == plNetClientMgr::GetInstance()->GetPlayerID())
|
|
|
|
{
|
|
|
|
keyObj = pyKey::New(plNetClientMgr::GetInstance()->GetLocalPlayerKey());
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
plNetTransportMember **members = nil;
|
|
|
|
plNetClientMgr::GetInstance()->TransportMgr().GetMemberListDistSorted( members );
|
|
|
|
|
|
|
|
if( members != nil)
|
|
|
|
{
|
|
|
|
for(int i = 0; i < plNetClientMgr::GetInstance()->TransportMgr().GetNumMembers(); i++ )
|
|
|
|
{
|
|
|
|
plNetTransportMember *mbr = members[ i ];
|
|
|
|
if( mbr != nil && mbr->GetAvatarKey() != nil && mbr->GetPlayerID() == clientID)
|
|
|
|
{
|
|
|
|
keyObj = pyKey::New(mbr->GetAvatarKey());
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
delete [] members;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (keyObj)
|
|
|
|
return keyObj;
|
|
|
|
else
|
|
|
|
PYTHON_RETURN_NONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int cyMisc::GetClientIDFromAvatarKey(pyKey& avatar)
|
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
if (plNetClientMgr::GetInstance()->GetLocalPlayerKey() == avatar.getKey())
|
|
|
|
{
|
|
|
|
return (plNetClientMgr::GetInstance()->GetPlayerID());
|
|
|
|
}
|
|
|
|
plNetTransportMember **members = nil;
|
|
|
|
plNetClientMgr::GetInstance()->TransportMgr().GetMemberListDistSorted( members );
|
|
|
|
if( members != nil)
|
|
|
|
{
|
|
|
|
for(int i = 0; i < plNetClientMgr::GetInstance()->TransportMgr().GetNumMembers(); i++ )
|
|
|
|
{
|
|
|
|
plNetTransportMember *mbr = members[ i ];
|
|
|
|
|
|
|
|
if( mbr != nil && mbr->GetAvatarKey() == avatar.getKey())
|
|
|
|
{
|
|
|
|
ret = mbr->GetPlayerID();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
delete [] members;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
int cyMisc::GetLocalClientID()
|
|
|
|
{
|
|
|
|
return (plNetClientMgr::GetInstance()->GetPlayerID());
|
|
|
|
}
|
|
|
|
|
|
|
|
hsBool cyMisc::ValidateKey(pyKey& key)
|
|
|
|
{
|
|
|
|
plKey pKey = key.getKey();
|
|
|
|
|
|
|
|
if (pKey && pKey->ObjectIsLoaded())
|
|
|
|
return true;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Function : GetClientName
|
|
|
|
// PARAMETERS :
|
|
|
|
//
|
|
|
|
// PURPOSE : Return the local net client (account) name
|
|
|
|
//
|
|
|
|
plString cyMisc::GetLocalClientName()
|
|
|
|
{
|
|
|
|
return plNetClientMgr::GetInstance()->GetPlayerName();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// Get Current age information - DEPRECIATED. Use ptDniInfoSource() object instead
|
|
|
|
//
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Function : GetAgeName
|
|
|
|
// Function : GetAgeTime
|
|
|
|
// Function : GetAgeGuid
|
|
|
|
// PARAMETERS :
|
|
|
|
//
|
|
|
|
// PURPOSE : Return the age name of the current age the local player is in
|
|
|
|
// : Return the current coordinates of the player within this age
|
|
|
|
// : Return the current time with the current age the player is in
|
|
|
|
// : Return the current guid of the instance of the age the player is in
|
|
|
|
//
|
|
|
|
|
|
|
|
const char * cyMisc::GetAgeName()
|
|
|
|
{
|
|
|
|
return NetCommGetAge()->ageDatasetName;
|
|
|
|
}
|
|
|
|
|
|
|
|
PyObject* cyMisc::GetAgeInfo()
|
|
|
|
{
|
|
|
|
plNetLinkingMgr* nmgr = plNetLinkingMgr::GetInstance();
|
|
|
|
if (nmgr)
|
|
|
|
{
|
|
|
|
plAgeLinkStruct* als = nmgr->GetAgeLink();
|
|
|
|
if (als)
|
|
|
|
return pyAgeInfoStruct::New(als->GetAgeInfo());
|
|
|
|
}
|
|
|
|
PYTHON_RETURN_NONE; // return none, not nil (cause it isn't really an error... or is it?)
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const char* cyMisc::GetPrevAgeName()
|
|
|
|
{
|
|
|
|
plNetLinkingMgr* nmgr = plNetLinkingMgr::GetInstance();
|
|
|
|
if (nmgr)
|
|
|
|
{
|
|
|
|
plAgeLinkStruct* als = nmgr->GetPrevAgeLink();
|
|
|
|
if (als)
|
|
|
|
return als->GetAgeInfo()->GetAgeFilename();
|
|
|
|
}
|
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
|
|
|
|
PyObject* cyMisc::GetPrevAgeInfo()
|
|
|
|
{
|
|
|
|
plNetLinkingMgr* nmgr = plNetLinkingMgr::GetInstance();
|
|
|
|
if (nmgr)
|
|
|
|
{
|
|
|
|
plAgeLinkStruct* als = nmgr->GetPrevAgeLink();
|
|
|
|
if (als)
|
|
|
|
return pyAgeInfoStruct::New(als->GetAgeInfo());
|
|
|
|
}
|
|
|
|
PYTHON_RETURN_NONE; // return none, not nil (cause it isn't really an error... or is it?)
|
|
|
|
}
|
|
|
|
|
|
|
|
// current time in current age
|
|
|
|
uint32_t cyMisc::GetAgeTime( void )
|
|
|
|
{
|
|
|
|
return VaultAgeGetAgeTime();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
time_t cyMisc::GetDniTime(void)
|
|
|
|
{
|
|
|
|
const plUnifiedTime utime = plNetClientMgr::GetInstance()->GetServerTime();
|
|
|
|
if ( utime.GetSecs() != 0)
|
|
|
|
return ConvertGMTtoDni(utime.GetSecs());
|
|
|
|
else
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
time_t cyMisc::GetServerTime(void)
|
|
|
|
{
|
|
|
|
const plUnifiedTime utime = plNetClientMgr::GetInstance()->GetServerTime();
|
|
|
|
return utime.GetSecs();
|
|
|
|
}
|
|
|
|
|
|
|
|
float cyMisc::GetAgeTimeOfDayPercent(void)
|
|
|
|
{
|
|
|
|
return plNetClientMgr::GetInstance()->GetCurrentAgeTimeOfDayPercent();
|
|
|
|
}
|
|
|
|
|
|
|
|
#define kMST (uint32_t)25200
|
|
|
|
#define kOneHour (uint32_t)3600
|
|
|
|
#define kOneDay (uint32_t)86400
|
|
|
|
|
|
|
|
time_t cyMisc::ConvertGMTtoDni(time_t gtime)
|
|
|
|
{
|
|
|
|
// convert to mountain time
|
|
|
|
time_t dtime = gtime - kMST;
|
|
|
|
plUnifiedTime utime = plUnifiedTime();
|
|
|
|
utime.SetSecs(dtime);
|
|
|
|
// check for daylight savings time in New Mexico and adjust
|
|
|
|
if ( utime.GetMonth() >= 3 && utime.GetMonth() <= 11 )
|
|
|
|
{
|
|
|
|
plUnifiedTime dstStart = plUnifiedTime();
|
|
|
|
dstStart.SetGMTime(utime.GetYear(),3,8,2,0,0);
|
|
|
|
// find first Sunday after (including) 3/8 (second Sunday of March)
|
|
|
|
int days_to_go = 7 - dstStart.GetDayOfWeek();
|
|
|
|
if (days_to_go == 7)
|
|
|
|
days_to_go = 0;
|
|
|
|
time_t dstStartSecs = dstStart.GetSecs() + days_to_go * kOneDay;
|
|
|
|
|
|
|
|
plUnifiedTime dstEnd = plUnifiedTime();
|
|
|
|
dstEnd.SetGMTime(utime.GetYear(),11,1,1,0,0);
|
|
|
|
// find first sunday after (including) 11/1 (first Sunday of November)
|
|
|
|
days_to_go = 7 - dstEnd.GetDayOfWeek();
|
|
|
|
if (days_to_go == 7)
|
|
|
|
days_to_go = 0;
|
|
|
|
time_t dstEndSecs = dstEnd.GetSecs() + days_to_go * kOneDay;
|
|
|
|
|
|
|
|
if ( dtime >= dstStartSecs && dtime < dstEndSecs )
|
|
|
|
// add hour for daylight savings time
|
|
|
|
dtime += kOneHour;
|
|
|
|
}
|
|
|
|
|
|
|
|
return dtime;
|
|
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Function : ExcludeRegionSet
|
|
|
|
// PARAMETERS : key - of the exclude region, ie. where to send the message
|
|
|
|
// state - what state of to set at:
|
|
|
|
// 0 = release
|
|
|
|
// 1 = clear
|
|
|
|
//
|
|
|
|
// PURPOSE : Sets the state of an exclude region
|
|
|
|
//
|
|
|
|
void cyMisc::ExcludeRegionSet(pyKey& sender, pyKey& exKey, uint16_t state)
|
|
|
|
{
|
|
|
|
plExcludeRegionMsg *msg = new plExcludeRegionMsg;
|
|
|
|
|
|
|
|
switch (state)
|
|
|
|
{
|
|
|
|
case kExRegClear:
|
|
|
|
msg->SetCmd(plExcludeRegionMsg::kClear);
|
|
|
|
break;
|
|
|
|
case kExRegRelease:
|
|
|
|
msg->SetCmd(plExcludeRegionMsg::kRelease);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
msg->SetSender(sender.getKey());
|
|
|
|
msg->AddReceiver(exKey.getKey());
|
|
|
|
plgDispatch::MsgSend( msg ); // whoosh... off it goes
|
|
|
|
}
|
|
|
|
|
|
|
|
void cyMisc::ExcludeRegionSetNow(pyKey& sender, pyKey& exKey, uint16_t state)
|
|
|
|
{
|
|
|
|
plExcludeRegionMsg *msg = new plExcludeRegionMsg;
|
|
|
|
|
|
|
|
switch (state)
|
|
|
|
{
|
|
|
|
case kExRegClear:
|
|
|
|
msg->SetCmd(plExcludeRegionMsg::kClear);
|
|
|
|
break;
|
|
|
|
case kExRegRelease:
|
|
|
|
msg->SetCmd(plExcludeRegionMsg::kRelease);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
msg->SetSender(sender.getKey());
|
|
|
|
msg->AddReceiver(exKey.getKey());
|
|
|
|
msg->fSynchFlags = plSynchedObject::kSendImmediately;
|
|
|
|
plgDispatch::MsgSend( msg ); // whoosh... off it goes
|
|
|
|
}
|
|
|
|
|
|
|
|
void cyMisc::FlashWindow()
|
|
|
|
{
|
|
|
|
plKey clientKey = hsgResMgr::ResMgr()->FindKey(kClient_KEY);
|
|
|
|
plClientMsg* pMsg = new plClientMsg(plClientMsg::kFlashWindow);
|
|
|
|
pMsg->Send(clientKey); // whoosh... off it goes
|
|
|
|
}
|
|
|
|
|
|
|
|
#include "hsTimer.h"
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Function : GetSeconds
|
|
|
|
// PARAMETERS :
|
|
|
|
//
|
|
|
|
// PURPOSE : Return the nunber of seconds elapsed
|
|
|
|
//
|
|
|
|
double cyMisc::GetSeconds()
|
|
|
|
{
|
|
|
|
return hsTimer::GetSeconds();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Function : GetSysSeconds
|
|
|
|
// PARAMETERS :
|
|
|
|
//
|
|
|
|
// PURPOSE : Return the number of system seconds elapsed
|
|
|
|
//
|
|
|
|
double cyMisc::GetSysSeconds()
|
|
|
|
{
|
|
|
|
return hsTimer::GetSysSeconds();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Function : GetDelSysSeconds
|
|
|
|
// PARAMETERS :
|
|
|
|
//
|
|
|
|
// PURPOSE : Return the frame delta seconds
|
|
|
|
//
|
|
|
|
float cyMisc::GetDelSysSeconds()
|
|
|
|
{
|
|
|
|
return hsTimer::GetDelSysSeconds();
|
|
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Function : LoadDialog
|
|
|
|
// PARAMETERS :
|
|
|
|
//
|
|
|
|
// PURPOSE : Return the frame delta seconds
|
|
|
|
//
|
|
|
|
void cyMisc::LoadDialog(const char* name)
|
|
|
|
{
|
|
|
|
pfGameGUIMgr *mgr = pfGameGUIMgr::GetInstance();
|
|
|
|
if ( mgr )
|
|
|
|
{
|
|
|
|
if ( !mgr->IsDialogLoaded(name) )
|
|
|
|
mgr->LoadDialog( name );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Load dialog and set the GUINotifyMsg receiver key
|
|
|
|
void cyMisc::LoadDialogK(const char* name, pyKey& rKey)
|
|
|
|
{
|
|
|
|
pfGameGUIMgr *mgr = pfGameGUIMgr::GetInstance();
|
|
|
|
if ( mgr )
|
|
|
|
{
|
|
|
|
// has the dialog been loaded yet?
|
|
|
|
if ( !mgr->IsDialogLoaded(name) )
|
|
|
|
// no then load and set handler
|
|
|
|
mgr->LoadDialog( name, rKey.getKey() );
|
|
|
|
else
|
|
|
|
// yes then just set the handler
|
|
|
|
mgr->SetDialogToNotify(name,rKey.getKey());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Load dialog and set the GUINotifyMsg receiver key
|
|
|
|
void cyMisc::LoadDialogKA(const char* name, pyKey& rKey, const char* ageName)
|
|
|
|
{
|
|
|
|
pfGameGUIMgr *mgr = pfGameGUIMgr::GetInstance();
|
|
|
|
if ( mgr )
|
|
|
|
{
|
|
|
|
// has the dialog been loaded yet?
|
|
|
|
if ( !mgr->IsDialogLoaded(name) )
|
|
|
|
// no then load and set handler
|
|
|
|
mgr->LoadDialog( name, rKey.getKey(), ageName );
|
|
|
|
else
|
|
|
|
// yes then just set the handler
|
|
|
|
mgr->SetDialogToNotify(name,rKey.getKey());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Function : UnLoadDialog
|
|
|
|
// PARAMETERS :
|
|
|
|
//
|
|
|
|
// PURPOSE : UnLoads the dialog by name
|
|
|
|
// : optionally sets the receiver key for the GUINotifyMsg
|
|
|
|
//
|
|
|
|
void cyMisc::UnloadDialog(const char* name)
|
|
|
|
{
|
|
|
|
pfGameGUIMgr *mgr = pfGameGUIMgr::GetInstance();
|
|
|
|
if ( mgr )
|
|
|
|
{
|
|
|
|
if ( mgr->IsDialogLoaded(name) )
|
|
|
|
mgr->UnloadDialog( name );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Function : IsDialogLoaded
|
|
|
|
// PARAMETERS :
|
|
|
|
//
|
|
|
|
// PURPOSE : Test to see if a dialog is loaded (according to the dialog manager)
|
|
|
|
//
|
|
|
|
hsBool cyMisc::IsDialogLoaded(const char* name)
|
|
|
|
{
|
|
|
|
pfGameGUIMgr *mgr = pfGameGUIMgr::GetInstance();
|
|
|
|
if ( mgr )
|
|
|
|
return mgr->IsDialogLoaded(name);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Function : ShowDialog
|
|
|
|
// Function : HideDialog
|
|
|
|
// PARAMETERS :
|
|
|
|
//
|
|
|
|
// PURPOSE : Show or Hide a dialog by name
|
|
|
|
//
|
|
|
|
void cyMisc::ShowDialog(const char* name)
|
|
|
|
{
|
|
|
|
pfGameGUIMgr *mgr = pfGameGUIMgr::GetInstance();
|
|
|
|
if ( mgr )
|
|
|
|
mgr->ShowDialog(name);
|
|
|
|
}
|
|
|
|
void cyMisc::HideDialog(const char* name)
|
|
|
|
{
|
|
|
|
pfGameGUIMgr *mgr = pfGameGUIMgr::GetInstance();
|
|
|
|
if ( mgr )
|
|
|
|
mgr->HideDialog(name);
|
|
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Function : GetDialogFromTagID
|
|
|
|
// PARAMETERS :
|
|
|
|
//
|
|
|
|
// PURPOSE : Return the frame delta seconds
|
|
|
|
//
|
|
|
|
PyObject* cyMisc::GetDialogFromTagID(uint32_t tag)
|
|
|
|
{
|
|
|
|
pfGameGUIMgr *mgr = pfGameGUIMgr::GetInstance();
|
|
|
|
if ( mgr )
|
|
|
|
{
|
|
|
|
// get the owner dialog modifier pointer
|
|
|
|
pfGUIDialogMod* pdialog = mgr->GetDialogFromTag(tag);
|
|
|
|
if ( pdialog )
|
|
|
|
return pyGUIDialog::New(pdialog->GetKey());
|
|
|
|
}
|
|
|
|
|
|
|
|
char errmsg[256];
|
|
|
|
sprintf(errmsg,"GUIDialog TagID %d not found",tag);
|
|
|
|
PyErr_SetString(PyExc_KeyError, errmsg);
|
|
|
|
return nil; // return nil, cause we threw an error
|
|
|
|
}
|
|
|
|
|
|
|
|
PyObject* cyMisc::GetDialogFromString(const char* name)
|
|
|
|
{
|
|
|
|
pfGameGUIMgr *mgr = pfGameGUIMgr::GetInstance();
|
|
|
|
if ( mgr )
|
|
|
|
{
|
|
|
|
// get the owner dialog modifier pointer
|
|
|
|
pfGUIDialogMod* pdialog = mgr->GetDialogFromString(name);
|
|
|
|
if ( pdialog )
|
|
|
|
return pyGUIDialog::New(pdialog->GetKey());
|
|
|
|
}
|
|
|
|
|
|
|
|
char errmsg[256];
|
|
|
|
sprintf(errmsg,"GUIDialog %s not found",name);
|
|
|
|
PyErr_SetString(PyExc_KeyError, errmsg);
|
|
|
|
return nil; // return nil, cause we threw an error
|
|
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Function : IsGUIModal
|
|
|
|
// PARAMETERS :
|
|
|
|
//
|
|
|
|
// PURPOSE : Returns true if the GUI is currently modal (and therefore blocking input)
|
|
|
|
//
|
|
|
|
bool cyMisc::IsGUIModal()
|
|
|
|
{
|
|
|
|
pfGameGUIMgr* mgr = pfGameGUIMgr::GetInstance();
|
|
|
|
if (mgr)
|
|
|
|
return mgr->IsModalBlocking();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Function : GetLocalAvatar
|
|
|
|
// Function : GetLocalPlayer
|
|
|
|
// PARAMETERS :
|
|
|
|
//
|
|
|
|
// PURPOSE : Return a pySceneobject of the local Avatar
|
|
|
|
// : Player - returns ptPlayer object
|
|
|
|
//
|
|
|
|
PyObject* cyMisc::GetLocalAvatar()
|
|
|
|
{
|
|
|
|
plSceneObject *so = plSceneObject::ConvertNoRef(plNetClientMgr::GetInstance()->GetLocalPlayer());
|
|
|
|
if ( so )
|
|
|
|
return pySceneObject::New(so->GetKey());
|
|
|
|
|
|
|
|
char errmsg[256];
|
|
|
|
sprintf(errmsg,"Local avatar not found");
|
|
|
|
PyErr_SetString(PyExc_NameError, errmsg);
|
|
|
|
return nil; // returns nil, cause we threw an error
|
|
|
|
}
|
|
|
|
|
|
|
|
PyObject* cyMisc::GetLocalPlayer()
|
|
|
|
{
|
|
|
|
return pyPlayer::New(plNetClientMgr::GetInstance()->GetLocalPlayerKey(),
|
|
|
|
plNetClientMgr::GetInstance()->GetPlayerName().c_str(),
|
|
|
|
plNetClientMgr::GetInstance()->GetPlayerID(),
|
|
|
|
0.0 );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if 1
|
|
|
|
#include "plStatusLog/plStatusLog.h"
|
|
|
|
//
|
|
|
|
// TEMP SCREEN PRINT CODE FOR NON-DBG TEXT DISPLAY
|
|
|
|
//
|
|
|
|
void cyMisc::PrintToScreen(const char* msg)
|
|
|
|
{
|
|
|
|
static plStatusLog* gStatusLog=nil;
|
|
|
|
if (gStatusLog==nil)
|
|
|
|
{
|
|
|
|
gStatusLog = plStatusLogMgr::GetInstance().CreateStatusLog( 32, "",
|
|
|
|
plStatusLog::kDontWriteFile | plStatusLog::kDeleteForMe | plStatusLog::kFilledBackground );
|
|
|
|
plStatusLogMgr::GetInstance().ToggleStatusLog(gStatusLog);
|
|
|
|
}
|
|
|
|
gStatusLog->AddLine(msg, plStatusLog::kBlue);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "plPipeline.h"
|
|
|
|
#include "plGImage/plMipmap.h"
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Function : GetPlayerList
|
|
|
|
// Function : GetPlayerListDistanceSorted
|
|
|
|
// PARAMETERS :
|
|
|
|
//
|
|
|
|
// PURPOSE : Get a list of players (other than self) that are playing the game
|
|
|
|
// : optionally get it sorted by distance
|
|
|
|
//
|
|
|
|
// RETURNS : Python object list of pyPlayer s
|
|
|
|
//
|
|
|
|
std::vector<PyObject*> cyMisc::GetPlayerList()
|
|
|
|
{
|
|
|
|
std::vector<PyObject*> pyPL;
|
|
|
|
plNetClientMgr* nc=plNetClientMgr::GetInstance();
|
|
|
|
|
|
|
|
if (!nc) // only ever really happens if they try to call us in max... I hope
|
|
|
|
return pyPL;
|
|
|
|
|
|
|
|
int i;
|
|
|
|
for( i = 0; i < nc->TransportMgr().GetNumMembers(); i++ )
|
|
|
|
{
|
|
|
|
plNetTransportMember *mbr = nc->TransportMgr().GetMember(i);
|
|
|
|
plKey avkey = mbr->GetAvatarKey();
|
|
|
|
if (avkey)
|
|
|
|
{
|
|
|
|
// only non-ignored people in list and not in ignore list
|
|
|
|
if ( !VaultAmIgnoringPlayer ( mbr->GetPlayerID()) )
|
|
|
|
{
|
|
|
|
PyObject* playerObj = pyPlayer::New(avkey, mbr->GetPlayerName().c_str(), mbr->GetPlayerID(), mbr->GetDistSq());
|
|
|
|
pyPlayer* player = pyPlayer::ConvertFrom(playerObj); // accesses internal pyPlayer object
|
|
|
|
|
|
|
|
// modifies playerObj
|
|
|
|
if ( mbr->IsCCR() )
|
|
|
|
player->SetCCRFlag(true);
|
|
|
|
if ( mbr->IsServer() )
|
|
|
|
player->SetServerFlag(true);
|
|
|
|
|
|
|
|
pyPL.push_back(playerObj);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return pyPL;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<PyObject*> cyMisc::GetPlayerListDistanceSorted()
|
|
|
|
{
|
|
|
|
std::vector<PyObject*> pyPL;
|
|
|
|
|
|
|
|
// get the sorted member list from the Net transport manager
|
|
|
|
plNetTransportMember **members = nil;
|
|
|
|
plNetClientMgr::GetInstance()->TransportMgr().GetMemberListDistSorted( members );
|
|
|
|
if( members != nil )
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
for( i = 0; i < plNetClientMgr::GetInstance()->TransportMgr().GetNumMembers(); i++ )
|
|
|
|
{
|
|
|
|
plNetTransportMember *mbr = members[ i ];
|
|
|
|
plKey avkey = mbr->GetAvatarKey();
|
|
|
|
if (avkey)
|
|
|
|
{
|
|
|
|
// only non-ignored people in list and not in ignore list
|
|
|
|
if ( !VaultAmIgnoringPlayer ( mbr->GetPlayerID()) )
|
|
|
|
{
|
|
|
|
PyObject* playerObj = pyPlayer::New(avkey, mbr->GetPlayerName().c_str(), mbr->GetPlayerID(), mbr->GetDistSq());
|
|
|
|
pyPlayer* player = pyPlayer::ConvertFrom(playerObj); // accesses internal pyPlayer object
|
|
|
|
|
|
|
|
// modifies playerObj
|
|
|
|
if ( mbr->IsCCR() )
|
|
|
|
player->SetCCRFlag(true);
|
|
|
|
if ( mbr->IsServer() )
|
|
|
|
player->SetServerFlag(true);
|
|
|
|
|
|
|
|
pyPL.push_back(playerObj);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
delete [] members;
|
|
|
|
}
|
|
|
|
return pyPL;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t cyMisc::GetMaxListenListSize()
|
|
|
|
{
|
|
|
|
return plNetListenList::kMaxListenListSize;
|
|
|
|
}
|
|
|
|
|
|
|
|
float cyMisc::GetMaxListenDistSq()
|
|
|
|
{
|
|
|
|
return plNetListenList::kMaxListenDistSq;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Function : SendRTChat
|
|
|
|
// PARAMETERS : from - is a pyPlayer of the person who is sending this
|
|
|
|
// : tolist - is a python list object, if empty then broadcast message
|
|
|
|
// : message - text string to send to others
|
|
|
|
// : flags - the flags of destiny... whatever that means
|
|
|
|
//
|
|
|
|
// PURPOSE : To send a real time chat message to a particualr user, a list of users
|
|
|
|
// : or broadcast it to everyone (within hearing distance?)
|
|
|
|
//
|
|
|
|
// RETURNS : the flags that were sent with the message (may be modified)
|
|
|
|
//
|
|
|
|
uint32_t cyMisc::SendRTChat(pyPlayer& from, const std::vector<pyPlayer*> & tolist, const char* message, uint32_t flags)
|
|
|
|
{
|
|
|
|
// create the messge that will contain the chat message
|
|
|
|
pfKIMsg *msg = new pfKIMsg( pfKIMsg::kHACKChatMsg );
|
|
|
|
msg->SetString( message );
|
|
|
|
msg->SetUser( from.GetPlayerName(), from.GetPlayerID() );
|
|
|
|
msg->SetFlags( flags );
|
|
|
|
msg->SetBCastFlag(plMessage::kNetPropagate | plMessage::kNetForce);
|
|
|
|
msg->SetBCastFlag(plMessage::kLocalPropagate, 0);
|
|
|
|
|
|
|
|
if (tolist.size() > 0)
|
|
|
|
{
|
|
|
|
if (flags & 8/* kRTChatInterAge in PlasmaKITypes.py */)
|
|
|
|
{
|
|
|
|
// allow inter-age routing of this msg
|
|
|
|
msg->SetBCastFlag( plMessage::kNetAllowInterAge );
|
|
|
|
}
|
|
|
|
// add net rcvrs to msg
|
|
|
|
int i;
|
|
|
|
for ( i=0 ; i<tolist.size() ; i++ )
|
|
|
|
{
|
|
|
|
if ( !VaultAmIgnoringPlayer( tolist[i]->GetPlayerID() ) )
|
|
|
|
msg->AddNetReceiver(tolist[i]->GetPlayerID());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t msgFlags = msg->GetFlags();
|
|
|
|
|
|
|
|
if (tolist.size() == 0 || (msg->GetNetReceivers() && msg->GetNetReceivers()->size() > 0))
|
|
|
|
msg->Send();
|
|
|
|
|
|
|
|
return msgFlags;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t cyMisc::SendRTChat(pyPlayer& from, const std::vector<pyPlayer*> & tolist, const wchar_t* message, uint32_t flags)
|
|
|
|
{
|
|
|
|
// create the messge that will contain the chat message
|
|
|
|
pfKIMsg *msg = new pfKIMsg( pfKIMsg::kHACKChatMsg );
|
|
|
|
msg->SetString( message );
|
|
|
|
msg->SetUser( from.GetPlayerName(), from.GetPlayerID() );
|
|
|
|
msg->SetFlags( flags );
|
|
|
|
msg->SetBCastFlag(plMessage::kNetPropagate | plMessage::kNetForce);
|
|
|
|
msg->SetBCastFlag(plMessage::kLocalPropagate, 0);
|
|
|
|
|
|
|
|
if (tolist.size() > 0)
|
|
|
|
{
|
|
|
|
if (flags & 8/* kRTChatInterAge in PlasmaKITypes.py */)
|
|
|
|
{
|
|
|
|
// allow inter-age routing of this msg
|
|
|
|
msg->SetBCastFlag( plMessage::kNetAllowInterAge );
|
|
|
|
}
|
|
|
|
// add net rcvrs to msg
|
|
|
|
for ( int i = 0 ; i < tolist.size() ; i++ )
|
|
|
|
{
|
|
|
|
if ( !VaultAmIgnoringPlayer( tolist[i]->GetPlayerID() ) )
|
|
|
|
msg->AddNetReceiver(tolist[i]->GetPlayerID());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t msgFlags = msg->GetFlags();
|
|
|
|
|
|
|
|
if (tolist.size() == 0 || (msg->GetNetReceivers() && msg->GetNetReceivers()->size() > 0))
|
|
|
|
msg->Send();
|
|
|
|
|
|
|
|
return msgFlags;
|
|
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Function : SendKIMessage
|
|
|
|
// PARAMETERS : command - the command type
|
|
|
|
// : value - extra value
|
|
|
|
//
|
|
|
|
// PURPOSE : Send message to the KI, to tell it things to do
|
|
|
|
//
|
|
|
|
// RETURNS : nothing
|
|
|
|
//
|
|
|
|
void cyMisc::SendKIMessage(uint32_t command, float value)
|
|
|
|
{
|
|
|
|
// create the mesage to send
|
|
|
|
pfKIMsg *msg = new pfKIMsg( (uint8_t)command );
|
|
|
|
|
|
|
|
// check to see if the value makes any sense
|
|
|
|
if ( command == pfKIMsg::kSetChatFadeDelay )
|
|
|
|
{
|
|
|
|
msg->SetDelay(value);
|
|
|
|
}
|
|
|
|
else if ( command == pfKIMsg::kSetTextChatAdminMode )
|
|
|
|
{
|
|
|
|
msg->SetFlags( value==1.0f ? pfKIMsg::kAdminMsg : 0 );
|
|
|
|
}
|
|
|
|
// send it off
|
|
|
|
plgDispatch::MsgSend( msg );
|
|
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Function : SendKIMessageS
|
|
|
|
// PARAMETERS : command - the command type
|
|
|
|
// : value - extra value as a string
|
|
|
|
//
|
|
|
|
// PURPOSE : Send message to the KI, to tell it things to do
|
|
|
|
//
|
|
|
|
// RETURNS : nothing
|
|
|
|
//
|
|
|
|
void cyMisc::SendKIMessageS(uint32_t command, const wchar_t* value)
|
|
|
|
{
|
|
|
|
// create the mesage to send
|
|
|
|
pfKIMsg *msg = new pfKIMsg( (uint8_t)command );
|
|
|
|
|
|
|
|
msg->SetString( value );
|
|
|
|
|
|
|
|
// send it off
|
|
|
|
plgDispatch::MsgSend( msg );
|
|
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Function : SendKIMessageI
|
|
|
|
// PARAMETERS : command - the command type
|
|
|
|
// : value - extra value as an int32_t
|
|
|
|
//
|
|
|
|
// PURPOSE : Send message to the KI, to tell it things to do
|
|
|
|
//
|
|
|
|
// RETURNS : nothing
|
|
|
|
//
|
|
|
|
void cyMisc::SendKIMessageI(uint32_t command, int32_t value)
|
|
|
|
{
|
|
|
|
// create the mesage to send
|
|
|
|
pfKIMsg *msg = new pfKIMsg( (uint8_t)command );
|
|
|
|
|
|
|
|
msg->SetIntValue(value);
|
|
|
|
|
|
|
|
// send it off
|
|
|
|
plgDispatch::MsgSend( msg );
|
|
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Function : SendKIMessageIReply
|
|
|
|
// PARAMETERS : command - the command type
|
|
|
|
// : value - extra value as an int32_t
|
|
|
|
//
|
|
|
|
// PURPOSE : Send message to the KI, to tell it things to do
|
|
|
|
//
|
|
|
|
// RETURNS : nothing
|
|
|
|
//
|
|
|
|
void cyMisc::SendKIGZMarkerMsg(int32_t markerNumber, pyKey& sender)
|
|
|
|
{
|
|
|
|
// create the mesage to send
|
|
|
|
pfKIMsg *msg = new pfKIMsg( pfKIMsg::kGZInRange );
|
|
|
|
|
|
|
|
msg->SetIntValue(markerNumber);
|
|
|
|
msg->SetSender(sender.getKey());
|
|
|
|
|
|
|
|
// send it off
|
|
|
|
plgDispatch::MsgSend( msg );
|
|
|
|
}
|
|
|
|
|
|
|
|
void cyMisc::SendKIRegisterImagerMsg(const char* imagerName, pyKey& sender)
|
|
|
|
{
|
|
|
|
pfKIMsg *msg = new pfKIMsg(pfKIMsg::kRegisterImager);
|
|
|
|
|
|
|
|
msg->SetString(imagerName);
|
|
|
|
msg->SetSender(sender.getKey());
|
|
|
|
|
|
|
|
plgDispatch::MsgSend( msg );
|
|
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Function : YesNoDialog
|
|
|
|
// PARAMETERS : sender - who set this and will get the notify
|
|
|
|
// : message - message to put up in YesNo dialog
|
|
|
|
//
|
|
|
|
// PURPOSE : Put up Yes/No dialog
|
|
|
|
//
|
|
|
|
// RETURNS : nothing
|
|
|
|
//
|
|
|
|
|
|
|
|
void cyMisc::YesNoDialog(pyKey& sender, const char* thestring)
|
|
|
|
{
|
|
|
|
// create the mesage to send
|
|
|
|
pfKIMsg *msg = new pfKIMsg( pfKIMsg::kYesNoDialog );
|
|
|
|
|
|
|
|
msg->SetSender(sender.getKey());
|
|
|
|
msg->SetString(thestring);
|
|
|
|
// send it off
|
|
|
|
plgDispatch::MsgSend( msg );
|
|
|
|
}
|
|
|
|
|
|
|
|
void cyMisc::YesNoDialog(pyKey& sender, std::wstring thestring)
|
|
|
|
{
|
|
|
|
char *temp = hsWStringToString(thestring.c_str());
|
|
|
|
YesNoDialog(sender,temp);
|
|
|
|
delete [] temp;
|
|
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Function : RateIt
|
|
|
|
// PARAMETERS : chonicleName - where to store the rating
|
|
|
|
// : thestring - the message in the RateIt dialog
|
|
|
|
// : onceFlag - flag to tell whether this is a onetime thing or ask everytime
|
|
|
|
//
|
|
|
|
// PURPOSE : Send message to the KI to tell it to ask the user to Rate something
|
|
|
|
//
|
|
|
|
// RETURNS : nothing
|
|
|
|
//
|
|
|
|
void cyMisc::RateIt(const char* chronicleName, const char* thestring, hsBool onceFlag)
|
|
|
|
{
|
|
|
|
// create the mesage to send
|
|
|
|
pfKIMsg *msg = new pfKIMsg( pfKIMsg::kRateIt );
|
|
|
|
|
|
|
|
msg->SetUser(chronicleName,0);
|
|
|
|
msg->SetString(thestring);
|
|
|
|
msg->SetIntValue(onceFlag);
|
|
|
|
// send it off
|
|
|
|
plgDispatch::MsgSend( msg );
|
|
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Function : SetPrivateChatList
|
|
|
|
// PARAMETERS : key - who's joining
|
|
|
|
//
|
|
|
|
// PURPOSE : Lock the local avatar into private vox messaging, and / or add new memebers to his chat list
|
|
|
|
//
|
|
|
|
// RETURNS : nothing
|
|
|
|
//
|
|
|
|
|
|
|
|
void cyMisc::SetPrivateChatList(const std::vector<pyPlayer*> & tolist)
|
|
|
|
{
|
|
|
|
if (tolist.size() > 0)
|
|
|
|
{
|
|
|
|
plNetVoiceListMsg* pMsg = new plNetVoiceListMsg(plNetVoiceListMsg::kForcedListenerMode);
|
|
|
|
for (int i=0 ; i<tolist.size() ; i++ )
|
|
|
|
pMsg->GetClientList()->Append(tolist[i]->GetPlayerID());
|
|
|
|
|
|
|
|
plKey k = plNetClientMgr::GetInstance()->GetLocalPlayerKey();
|
|
|
|
pMsg->SetRemovedKey(k);
|
|
|
|
pMsg->Send();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Function : ClearPrivateChatList
|
|
|
|
// PARAMETERS : key - who's leaving
|
|
|
|
//
|
|
|
|
// PURPOSE : Remove the local avatar from private vox messaging, and / or clear memebers from his chat list
|
|
|
|
//
|
|
|
|
// RETURNS : nothing
|
|
|
|
//
|
|
|
|
void cyMisc::ClearPrivateChatList(pyKey& member)
|
|
|
|
{
|
|
|
|
plNetVoiceListMsg* pMsg = new plNetVoiceListMsg(plNetVoiceListMsg::kDistanceMode);
|
|
|
|
plKey k = member.getKey();
|
|
|
|
pMsg->SetRemovedKey(k);
|
|
|
|
pMsg->Send();
|
|
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Function : ClearCameraStack
|
|
|
|
// PURPOSE : clear the camera stack
|
|
|
|
//
|
|
|
|
// RETURNS : nothing
|
|
|
|
//
|
|
|
|
|
|
|
|
void cyMisc::ClearCameraStack()
|
|
|
|
{
|
|
|
|
plVirtualCam1::Instance()->ClearStack();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool cyMisc::IsFirstPerson()
|
|
|
|
{
|
|
|
|
return (plVirtualCam1::Instance()->Is1stPersonCamera()!=0);
|
|
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Function : SendPetitionToCCR
|
|
|
|
// PARAMETERS : message - message to send to the CCR ("please help me!")
|
|
|
|
//
|
|
|
|
// PURPOSE : Send a petition to the CCR for help or questions
|
|
|
|
//
|
|
|
|
void cyMisc::SendPetitionToCCR(const char* message)
|
|
|
|
{
|
|
|
|
SendPetitionToCCRI(message,plNetCommon::PetitionTypes::kGeneralHelp,nil);
|
|
|
|
}
|
|
|
|
void cyMisc::SendPetitionToCCRI(const char* message, uint8_t reason,const char* title)
|
|
|
|
{
|
|
|
|
// create the mesage to send
|
|
|
|
plCCRPetitionMsg *msg = new plCCRPetitionMsg();
|
|
|
|
msg->SetNote(message);
|
|
|
|
msg->SetType(reason);
|
|
|
|
if (title)
|
|
|
|
msg->SetTitle(title);
|
|
|
|
// send it off
|
|
|
|
plgDispatch::MsgSend( msg );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Function : SendChatToCCR
|
|
|
|
// PARAMETERS : message - message to send to the CCR ("please help me!")
|
|
|
|
//
|
|
|
|
// PURPOSE : Send a chat message to the CCR for help or questions
|
|
|
|
//
|
|
|
|
void cyMisc::SendChatToCCR(const char* message,int32_t CCRPlayerID)
|
|
|
|
{
|
|
|
|
// create the mesage to send
|
|
|
|
plCCRCommunicationMsg *msg = new plCCRCommunicationMsg();
|
|
|
|
msg->SetMessage(message);
|
|
|
|
msg->SetType(plCCRCommunicationMsg::kReturnChatMsg);
|
|
|
|
msg->SetBCastFlag(plMessage::kNetAllowInterAge);
|
|
|
|
msg->SetBCastFlag(plMessage::kNetPropagate);
|
|
|
|
msg->SetBCastFlag(plMessage::kNetForce);
|
|
|
|
msg->SetBCastFlag(plMessage::kLocalPropagate,0);
|
|
|
|
msg->AddNetReceiver( CCRPlayerID );
|
|
|
|
msg->Send();
|
|
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Function : GetNumRemotePlayers
|
|
|
|
//
|
|
|
|
// PURPOSE : return the number of remote players connected
|
|
|
|
//
|
|
|
|
int cyMisc::GetNumRemotePlayers()
|
|
|
|
{
|
|
|
|
return plNetClientMgr::GetInstance()->RemotePlayerKeys().size();
|
|
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Function : Paging functions
|
|
|
|
// PARAMETERS : nodeName - name of the page to load
|
|
|
|
//
|
|
|
|
// PURPOSE : page in, hold or out a particular node
|
|
|
|
//
|
|
|
|
|
|
|
|
void cyMisc::PageInNodes(const std::vector<std::string> & nodeNames, const char* age)
|
|
|
|
{
|
|
|
|
if (hsgResMgr::ResMgr())
|
|
|
|
{
|
|
|
|
plSynchEnabler ps(false); // disable dirty tracking while paging in
|
|
|
|
plClientMsg* msg = new plClientMsg(plClientMsg::kLoadRoom);
|
|
|
|
plKey clientKey = hsgResMgr::ResMgr()->FindKey(kClient_KEY);
|
|
|
|
msg->AddReceiver(clientKey);
|
|
|
|
|
|
|
|
int numNames = nodeNames.size();
|
|
|
|
for (int i = 0; i < numNames; i++)
|
|
|
|
msg->AddRoomLoc(plKeyFinder::Instance().FindLocation(age ? age : NetCommGetAge()->ageDatasetName, nodeNames[i].c_str()));
|
|
|
|
|
|
|
|
msg->Send();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void cyMisc::PageOutNode(const char* nodeName)
|
|
|
|
{
|
|
|
|
if ( hsgResMgr::ResMgr() )
|
|
|
|
{
|
|
|
|
plSynchEnabler ps(false); // disable dirty tracking while paging out
|
|
|
|
plClientMsg* pMsg1 = new plClientMsg(plClientMsg::kUnloadRoom);
|
|
|
|
plKey clientKey = hsgResMgr::ResMgr()->FindKey( kClient_KEY );
|
|
|
|
pMsg1->AddReceiver( clientKey );
|
|
|
|
pMsg1->AddRoomLoc(plKeyFinder::Instance().FindLocation(nil, nodeName));
|
|
|
|
plgDispatch::MsgSend(pMsg1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#include "plAvatar/plArmatureMod.h"
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Function : LimitAvatarLOD
|
|
|
|
// PARAMETERS : LODlimit - number of to limit the LOD to
|
|
|
|
//
|
|
|
|
// PURPOSE : sets the avatar LOD limit
|
|
|
|
//
|
|
|
|
void cyMisc::LimitAvatarLOD(int LODlimit)
|
|
|
|
{
|
|
|
|
if(LODlimit >= 0 && LODlimit <= 2)
|
|
|
|
plArmatureLODMod::fMinLOD = LODlimit;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "plPipeline/plFogEnvironment.h"
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Function : Set fog default functions
|
|
|
|
// PARAMETERS : floats - the parameters
|
|
|
|
//
|
|
|
|
// PURPOSE : sets the fog defaults
|
|
|
|
//
|
|
|
|
void cyMisc::FogSetDefColor(pyColor& color)
|
|
|
|
{
|
|
|
|
if ( fPipeline )
|
|
|
|
{
|
|
|
|
hsColorRGBA hcolor = color.getColor();
|
|
|
|
hcolor.a = 1.0f; // make sure that alpha is 1
|
|
|
|
plFogEnvironment env = fPipeline->GetDefaultFogEnviron();
|
|
|
|
env.SetColor( hcolor );
|
|
|
|
fPipeline->SetDefaultFogEnviron( &env );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void cyMisc::FogSetDefLinear(float start, float end, float density)
|
|
|
|
{
|
|
|
|
if ( fPipeline )
|
|
|
|
{
|
|
|
|
plFogEnvironment env = fPipeline->GetDefaultFogEnviron();
|
|
|
|
env.Set( start, end, density );
|
|
|
|
fPipeline->SetDefaultFogEnviron( &env );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void cyMisc::FogSetDefExp(float end, float density)
|
|
|
|
{
|
|
|
|
if ( fPipeline )
|
|
|
|
{
|
|
|
|
plFogEnvironment env = fPipeline->GetDefaultFogEnviron();
|
|
|
|
env.SetExp( plFogEnvironment::kExpFog, end, density );
|
|
|
|
fPipeline->SetDefaultFogEnviron( &env );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void cyMisc::FogSetDefExp2(float end, float density)
|
|
|
|
{
|
|
|
|
if ( fPipeline )
|
|
|
|
{
|
|
|
|
plFogEnvironment env = fPipeline->GetDefaultFogEnviron();
|
|
|
|
env.SetExp( plFogEnvironment::kExp2Fog, end, density );
|
|
|
|
fPipeline->SetDefaultFogEnviron( &env );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void cyMisc::SetClearColor(float red, float green, float blue)
|
|
|
|
{
|
|
|
|
// do this command via the console to keep the maxplugins from barfing
|
|
|
|
char command[256];
|
|
|
|
sprintf(command,"Graphics.Renderer.SetClearColor %f %f %f",red,green,blue);
|
|
|
|
// create message to send to the console
|
|
|
|
plControlEventMsg* pMsg = new plControlEventMsg;
|
|
|
|
pMsg->SetBCastFlag(plMessage::kBCastByType);
|
|
|
|
pMsg->SetControlCode(B_CONTROL_CONSOLE_COMMAND);
|
|
|
|
pMsg->SetControlActivated(true);
|
|
|
|
pMsg->SetCmdString(command);
|
|
|
|
plgDispatch::MsgSend( pMsg ); // whoosh... off it goes
|
|
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Function : Enable / disable cursor fade for avatar
|
|
|
|
// PARAMETERS :
|
|
|
|
//
|
|
|
|
// PURPOSE : turns avatar fade out on / off
|
|
|
|
//
|
|
|
|
|
|
|
|
void cyMisc::EnableAvatarCursorFade()
|
|
|
|
{
|
|
|
|
plNetClientMgr* nmgr = plNetClientMgr::GetInstance();
|
|
|
|
if (nmgr)
|
|
|
|
{
|
|
|
|
plIfaceFadeAvatarMsg* iMsg = new plIfaceFadeAvatarMsg;
|
|
|
|
iMsg->SetSubjectKey(nmgr->GetLocalPlayerKey());
|
|
|
|
iMsg->SetBCastFlag(plMessage::kBCastByExactType);
|
|
|
|
iMsg->SetBCastFlag(plMessage::kNetPropagate, false);
|
|
|
|
iMsg->Enable();
|
|
|
|
iMsg->Send();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void cyMisc::DisableAvatarCursorFade()
|
|
|
|
{
|
|
|
|
plNetClientMgr* nmgr = plNetClientMgr::GetInstance();
|
|
|
|
if (nmgr)
|
|
|
|
{
|
|
|
|
plIfaceFadeAvatarMsg* iMsg = new plIfaceFadeAvatarMsg;
|
|
|
|
iMsg->SetSubjectKey(nmgr->GetLocalPlayerKey());
|
|
|
|
iMsg->SetBCastFlag(plMessage::kBCastByExactType);
|
|
|
|
iMsg->SetBCastFlag(plMessage::kNetPropagate, false);
|
|
|
|
iMsg->Disable();
|
|
|
|
iMsg->Send();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void cyMisc::FadeLocalPlayer(hsBool fade)
|
|
|
|
{
|
|
|
|
plNetClientMgr* nmgr = plNetClientMgr::GetInstance();
|
|
|
|
if (nmgr)
|
|
|
|
{
|
|
|
|
plCameraTargetFadeMsg* pMsg = new plCameraTargetFadeMsg;
|
|
|
|
pMsg->SetFadeOut(fade);
|
|
|
|
pMsg->SetSubjectKey(nmgr->GetLocalPlayerKey());
|
|
|
|
pMsg->SetBCastFlag(plMessage::kBCastByExactType);
|
|
|
|
pMsg->SetBCastFlag(plMessage::kNetPropagate, false);
|
|
|
|
pMsg->AddReceiver(nmgr->GetLocalPlayerKey());
|
|
|
|
plgDispatch::MsgSend(pMsg);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Function : offer linking book functions
|
|
|
|
// PARAMETERS :
|
|
|
|
//
|
|
|
|
// PURPOSE : manage offering public (pedestal) books
|
|
|
|
//
|
|
|
|
|
|
|
|
void cyMisc::EnableOfferBookMode(pyKey& selfkey, const char* ageFilename, const char* ageInstanceName)
|
|
|
|
{
|
|
|
|
plInputIfaceMgrMsg* pMsg = new plInputIfaceMgrMsg(plInputIfaceMgrMsg::kSetOfferBookMode);
|
|
|
|
pMsg->SetSender(selfkey.getKey());
|
|
|
|
pMsg->SetAgeFileName(ageFilename);
|
|
|
|
pMsg->SetAgeName(ageInstanceName);
|
|
|
|
pMsg->Send();
|
|
|
|
}
|
|
|
|
|
|
|
|
void cyMisc::DisableOfferBookMode()
|
|
|
|
{
|
|
|
|
plInputIfaceMgrMsg* pMsg = new plInputIfaceMgrMsg(plInputIfaceMgrMsg::kClearOfferBookMode);
|
|
|
|
pMsg->Send();
|
|
|
|
}
|
|
|
|
|
|
|
|
void cyMisc::NotifyOffererPublicLinkCompleted(uint32_t offerer)
|
|
|
|
{
|
|
|
|
plInputIfaceMgrMsg* pMsg = new plInputIfaceMgrMsg(plInputIfaceMgrMsg::kNotifyOfferCompleted, plNetClientMgr::GetInstance()->GetPlayerID());
|
|
|
|
pMsg->SetSender(plNetClientMgr::GetInstance()->GetLocalPlayerKey());
|
|
|
|
if (offerer != plNetClientMgr::GetInstance()->GetPlayerID())
|
|
|
|
{
|
|
|
|
pMsg->SetBCastFlag( plMessage::kNetPropagate );
|
|
|
|
pMsg->SetBCastFlag( plMessage::kNetForce );
|
|
|
|
pMsg->SetBCastFlag( plMessage::kLocalPropagate, 0 );
|
|
|
|
pMsg->AddNetReceiver( offerer );
|
|
|
|
}
|
|
|
|
|
|
|
|
pMsg->Send();
|
|
|
|
}
|
|
|
|
|
|
|
|
void cyMisc::NotifyOffererPublicLinkRejected(uint32_t offerer)
|
|
|
|
{
|
|
|
|
plInputIfaceMgrMsg* pMsg = new plInputIfaceMgrMsg(plInputIfaceMgrMsg::kNotifyOfferRejected);
|
|
|
|
pMsg->SetSender(plNetClientMgr::GetInstance()->GetLocalPlayerKey());
|
|
|
|
if (offerer != plNetClientMgr::GetInstance()->GetPlayerID())
|
|
|
|
{
|
|
|
|
pMsg->SetBCastFlag( plMessage::kNetPropagate );
|
|
|
|
pMsg->SetBCastFlag( plMessage::kNetForce );
|
|
|
|
pMsg->SetBCastFlag( plMessage::kLocalPropagate, 0 );
|
|
|
|
pMsg->AddNetReceiver( offerer );
|
|
|
|
}
|
|
|
|
|
|
|
|
pMsg->Send();
|
|
|
|
ToggleAvatarClickability(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
void cyMisc::NotifyOffererPublicLinkAccepted(uint32_t offerer)
|
|
|
|
{
|
|
|
|
plInputIfaceMgrMsg* pMsg = new plInputIfaceMgrMsg(plInputIfaceMgrMsg::kNotifyOfferAccepted);
|
|
|
|
pMsg->SetSender(plNetClientMgr::GetInstance()->GetLocalPlayerKey());
|
|
|
|
if (offerer != plNetClientMgr::GetInstance()->GetPlayerID())
|
|
|
|
{
|
|
|
|
pMsg->SetBCastFlag( plMessage::kNetPropagate );
|
|
|
|
pMsg->SetBCastFlag( plMessage::kNetForce );
|
|
|
|
pMsg->SetBCastFlag( plMessage::kLocalPropagate, 0 );
|
|
|
|
pMsg->AddNetReceiver( offerer );
|
|
|
|
}
|
|
|
|
|
|
|
|
pMsg->Send();
|
|
|
|
}
|
|
|
|
|
|
|
|
void cyMisc::ToggleAvatarClickability(hsBool on)
|
|
|
|
{
|
|
|
|
plInputIfaceMgrMsg* pMsg = 0;
|
|
|
|
if (on)
|
|
|
|
pMsg = new plInputIfaceMgrMsg(plInputIfaceMgrMsg::kGUIEnableAvatarClickable);
|
|
|
|
else
|
|
|
|
pMsg = new plInputIfaceMgrMsg(plInputIfaceMgrMsg::kGUIDisableAvatarClickable);
|
|
|
|
plKey k = plNetClientMgr::GetInstance()->GetLocalPlayerKey();
|
|
|
|
pMsg->SetAvKey(k);
|
|
|
|
pMsg->SetBCastFlag(plMessage::kNetPropagate);
|
|
|
|
pMsg->SetBCastFlag(plMessage::kNetForce);
|
|
|
|
pMsg->Send();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void cyMisc::SetShareSpawnPoint(const char* spawnPoint)
|
|
|
|
{
|
|
|
|
plInputIfaceMgrMsg* pMsg = new plInputIfaceMgrMsg(plInputIfaceMgrMsg::kSetShareSpawnPoint);
|
|
|
|
plKey k = plNetClientMgr::GetInstance()->GetLocalPlayerKey();
|
|
|
|
pMsg->SetSender(k);
|
|
|
|
pMsg->SetSpawnPoint(spawnPoint);
|
|
|
|
pMsg->Send();
|
|
|
|
}
|
|
|
|
|
|
|
|
void cyMisc::SetShareAgeInstanceGuid(const Uuid& guid)
|
|
|
|
{
|
|
|
|
plInputIfaceMgrMsg* pMsg = new plInputIfaceMgrMsg(plInputIfaceMgrMsg::kSetShareAgeInstanceGuid);
|
|
|
|
plKey k = plNetClientMgr::GetInstance()->GetLocalPlayerKey();
|
|
|
|
pMsg->SetSender(k);
|
|
|
|
pMsg->SetAgeInstanceGuid(guid);
|
|
|
|
pMsg->Send();
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Function : GetCCRAwayStatus
|
|
|
|
// PARAMETERS :
|
|
|
|
//
|
|
|
|
// PURPOSE : Returns current status of CCR dept
|
|
|
|
//
|
|
|
|
hsBool cyMisc::IsCCRAwayStatus()
|
|
|
|
{
|
|
|
|
return !VaultGetCCRStatus();
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Function : AmCCR
|
|
|
|
// PARAMETERS :
|
|
|
|
//
|
|
|
|
// PURPOSE : Returns true if local player is a CCR
|
|
|
|
//
|
|
|
|
hsBool cyMisc::AmCCR()
|
|
|
|
{
|
|
|
|
if ( plNetClientApp::GetInstance() )
|
|
|
|
return plNetClientApp::GetInstance()->AmCCR();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Function : AcceptInviteInGame
|
|
|
|
// PARAMETERS : Friend's Name, Invite Key
|
|
|
|
//
|
|
|
|
// PURPOSE : Send's a VaultTask to the server to perform the invite
|
|
|
|
//
|
|
|
|
void cyMisc::AcceptInviteInGame(const char* friendName, const char* inviteKey)
|
|
|
|
{
|
|
|
|
hsAssert(false, "eric, implement me");
|
|
|
|
#if 0
|
|
|
|
plNetClientMgr* nc = plNetClientMgr::GetInstance();
|
|
|
|
if (nc)
|
|
|
|
{
|
|
|
|
plNetMsgVaultTask msg;
|
|
|
|
msg.SetNetProtocol(kNetProtocolCli2Auth);
|
|
|
|
msg.SetTopic(plNetCommon::VaultTasks::kFriendInvite);
|
|
|
|
msg.GetArgs()->AddString(plNetCommon::VaultTaskArgs::kFriendName,friendName);
|
|
|
|
msg.GetArgs()->AddString(plNetCommon::VaultTaskArgs::kInviteKey,inviteKey);
|
|
|
|
nc->SendMsg(&msg);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Function : GetLanguage
|
|
|
|
// PARAMETERS :
|
|
|
|
//
|
|
|
|
// PURPOSE : Returns the current language the game is in
|
|
|
|
//
|
|
|
|
int cyMisc::GetLanguage()
|
|
|
|
{
|
|
|
|
return int(plLocalization::GetLanguage());
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Function : UsingUnicode
|
|
|
|
// PARAMETERS :
|
|
|
|
//
|
|
|
|
// PURPOSE : Returns true if the current language uses Unicode (like Japanese)
|
|
|
|
//
|
|
|
|
bool cyMisc::UsingUnicode()
|
|
|
|
{
|
|
|
|
return plLocalization::UsingUnicode();
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// particle system management
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
#include "plMessage/plParticleUpdateMsg.h"
|
|
|
|
#include "plParticleSystem/plParticleSystem.h"
|
|
|
|
#include "plParticleSystem/plParticleEffect.h"
|
|
|
|
void cyMisc::TransferParticlesToKey(pyKey& fromKey, pyKey& toKey, int numParticles)
|
|
|
|
{
|
|
|
|
plKey frKey = fromKey.getKey();
|
|
|
|
plSceneObject* so = plSceneObject::ConvertNoRef(toKey.getKey()->ObjectIsLoaded());
|
|
|
|
if (so == nil)
|
|
|
|
return;
|
|
|
|
|
|
|
|
plArmatureMod *avMod = plAvatarMgr::GetInstance()->GetLocalAvatar();
|
|
|
|
|
|
|
|
plParticleTransferMsg* pMsg = new plParticleTransferMsg(nil, avMod->GetKey(), 0, frKey, numParticles);
|
|
|
|
pMsg->SetBCastFlag(plMessage::kNetPropagate);
|
|
|
|
pMsg->SetBCastFlag(plMessage::kNetForce);
|
|
|
|
pMsg->Send();
|
|
|
|
}
|
|
|
|
|
|
|
|
void cyMisc::SetParticleDissentPoint(float x, float y, float z, pyKey& particles)
|
|
|
|
{
|
|
|
|
plKey frKey = particles.getKey();
|
|
|
|
plSceneObject* pObj = plSceneObject::ConvertNoRef(particles.getKey()->ObjectIsLoaded());
|
|
|
|
if (!pObj)
|
|
|
|
return;
|
|
|
|
const plParticleSystem *sys = plParticleSystem::ConvertNoRef(pObj->GetModifierByType(plParticleSystem::Index()));
|
|
|
|
if (sys == nil)
|
|
|
|
{
|
|
|
|
const plModifier* pArm = pObj->GetModifierByType(plArmatureMod::Index());
|
|
|
|
if (pArm)
|
|
|
|
{
|
|
|
|
// it's the avatar
|
|
|
|
const plArmatureMod* pCArm = (const plArmatureMod*)pArm;
|
|
|
|
plArmatureMod* pNonConstArm = const_cast<plArmatureMod*>(pCArm);
|
|
|
|
pObj = pNonConstArm->GetFollowerParticleSystemSO();
|
|
|
|
if (!pObj)
|
|
|
|
return;
|
|
|
|
else
|
|
|
|
sys = plParticleSystem::ConvertNoRef(pObj->GetModifierByType(plParticleSystem::Index()));
|
|
|
|
|
|
|
|
}
|
|
|
|
if (sys == nil)
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
plParticleEffect *flock = sys->GetEffect(plParticleFlockEffect::Index());
|
|
|
|
if (flock)
|
|
|
|
{
|
|
|
|
(new plParticleFlockMsg(nil, flock->GetKey(), 0, plParticleFlockMsg::kFlockCmdSetDissentPoint, x, y, z))->Send();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void cyMisc::SetParticleOffset(float x, float y, float z, pyKey& particles)
|
|
|
|
{
|
|
|
|
plKey frKey = particles.getKey();
|
|
|
|
plSceneObject* pObj = plSceneObject::ConvertNoRef(particles.getKey()->ObjectIsLoaded());
|
|
|
|
if (!pObj)
|
|
|
|
return;
|
|
|
|
const plParticleSystem *sys = plParticleSystem::ConvertNoRef(pObj->GetModifierByType(plParticleSystem::Index()));
|
|
|
|
if (sys == nil)
|
|
|
|
{
|
|
|
|
const plModifier* pArm = pObj->GetModifierByType(plArmatureMod::Index());
|
|
|
|
if (pArm)
|
|
|
|
{
|
|
|
|
// it's the avatar
|
|
|
|
const plArmatureMod* pCArm = (const plArmatureMod*)pArm;
|
|
|
|
plArmatureMod* pNonConstArm = const_cast<plArmatureMod*>(pCArm);
|
|
|
|
pObj = pNonConstArm->GetFollowerParticleSystemSO();
|
|
|
|
if (!pObj)
|
|
|
|
return;
|
|
|
|
else
|
|
|
|
sys = plParticleSystem::ConvertNoRef(pObj->GetModifierByType(plParticleSystem::Index()));
|
|
|
|
|
|
|
|
}
|
|
|
|
if (sys == nil)
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
plParticleEffect *flock = sys->GetEffect(plParticleFlockEffect::Index());
|
|
|
|
if (flock)
|
|
|
|
{
|
|
|
|
(new plParticleFlockMsg(nil, flock->GetKey(), 0, plParticleFlockMsg::kFlockCmdSetOffset, x, y, z))->Send();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void cyMisc::KillParticles(float time, float pct, pyKey& particles)
|
|
|
|
{
|
|
|
|
plKey frKey = particles.getKey();
|
|
|
|
plSceneObject* pObj = plSceneObject::ConvertNoRef(particles.getKey()->ObjectIsLoaded());
|
|
|
|
if (!pObj)
|
|
|
|
return;
|
|
|
|
const plParticleSystem *sys = plParticleSystem::ConvertNoRef(pObj->GetModifierByType(plParticleSystem::Index()));
|
|
|
|
if (sys == nil)
|
|
|
|
{
|
|
|
|
const plModifier* pArm = pObj->GetModifierByType(plArmatureMod::Index());
|
|
|
|
if (pArm)
|
|
|
|
{
|
|
|
|
// it's the avatar
|
|
|
|
const plArmatureMod* pCArm = (const plArmatureMod*)pArm;
|
|
|
|
plArmatureMod* pNonConstArm = const_cast<plArmatureMod*>(pCArm);
|
|
|
|
pObj = pNonConstArm->GetFollowerParticleSystemSO();
|
|
|
|
if (!pObj)
|
|
|
|
return;
|
|
|
|
else
|
|
|
|
sys = plParticleSystem::ConvertNoRef(pObj->GetModifierByType(plParticleSystem::Index()));
|
|
|
|
|
|
|
|
}
|
|
|
|
if (sys == nil)
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
plParticleEffect *flock = sys->GetEffect(plParticleFlockEffect::Index());
|
|
|
|
if (flock)
|
|
|
|
{
|
|
|
|
plParticleKillMsg* pMsg = new plParticleKillMsg(nil, frKey, 0, pct, time, plParticleKillMsg::kParticleKillPercentage | plParticleKillMsg::kParticleKillImmortalOnly);
|
|
|
|
pMsg->SetBCastFlag(plMessage::kNetPropagate);
|
|
|
|
pMsg->SetBCastFlag(plMessage::kNetForce);
|
|
|
|
pMsg->SetBCastFlag(plMessage::kPropagateToChildren);
|
|
|
|
pMsg->SetBCastFlag(plMessage::kPropagateToModifiers);
|
|
|
|
pMsg->Send();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int cyMisc::GetNumParticles(pyKey& host)
|
|
|
|
{
|
|
|
|
plSceneObject* pObj = plSceneObject::ConvertNoRef(host.getKey()->ObjectIsLoaded());
|
|
|
|
if (!pObj)
|
|
|
|
return 0;
|
|
|
|
const plModifier* pArm = pObj->GetModifierByType(plArmatureMod::Index());
|
|
|
|
if (pArm)
|
|
|
|
{
|
|
|
|
// it's the avatar
|
|
|
|
const plArmatureMod* pCArm = (const plArmatureMod*)pArm;
|
|
|
|
plArmatureMod* pNonConstArm = const_cast<plArmatureMod*>(pCArm);
|
|
|
|
pObj = pNonConstArm->GetFollowerParticleSystemSO();
|
|
|
|
if (!pObj)
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
const plModifier* pPart = pObj->GetModifierByType(plParticleSystem::Index());
|
|
|
|
if (!pPart)
|
|
|
|
return 0;
|
|
|
|
return ((const plParticleSystem*)pPart)->GetNumValidParticles(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void cyMisc::SetLightColorValue(pyKey& light, const plString& lightName, float r, float g, float b, float a)
|
|
|
|
{
|
|
|
|
// lightName is the name of the light object attached to the light that we want to talk to
|
|
|
|
// for the bug lights, this would be "RTOmni-BugLightTest"
|
|
|
|
plSceneObject* pObj = plSceneObject::ConvertNoRef(light.getKey()->ObjectIsLoaded());
|
|
|
|
if (!pObj)
|
|
|
|
return;
|
|
|
|
|
|
|
|
plObjInterface* pIface = pObj->GetGenericInterface(plLightInfo::Index());
|
|
|
|
if (pIface)
|
|
|
|
{
|
|
|
|
// we are a light ourselves... are we the one they are looking for?
|
|
|
|
if (lightName != pObj->GetKeyName())
|
|
|
|
pIface = nil; // not the one they want, check our children
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!pIface)
|
|
|
|
{
|
|
|
|
// recurse through our children...
|
|
|
|
for (int i = 0; i < pObj->GetCoordinateInterface()->GetNumChildren(); i++)
|
|
|
|
{
|
|
|
|
const plSceneObject* child = pObj->GetCoordinateInterface()->GetChild(i)->GetOwner();
|
|
|
|
if (child)
|
|
|
|
{
|
|
|
|
pIface = child->GetGenericInterface(plLightInfo::Index());
|
|
|
|
if (pIface)
|
|
|
|
{
|
|
|
|
// found a child... is it the one we want?
|
|
|
|
if (lightName != child->GetKeyName())
|
|
|
|
pIface = nil; // not the child we want, keep looking
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (pIface)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (pIface)
|
|
|
|
{
|
|
|
|
plLightInfo* pLight = (plLightInfo*)pIface;
|
|
|
|
hsColorRGBA c;
|
|
|
|
c.Set(r,g,b,a);
|
|
|
|
pLight->SetDiffuse(c);
|
|
|
|
pLight->SetDiffuse(c);
|
|
|
|
pLight->SetSpecular(c);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#include "pnMessage/plEnableMsg.h"
|
|
|
|
void cyMisc::SetLightAnimationOn(pyKey& light, const plString& lightName, hsBool start)
|
|
|
|
{
|
|
|
|
// lightName is the name of the light object attached to the light that we want to talk to
|
|
|
|
// for the bug lights, this would be "RTOmni-BugLightTest"
|
|
|
|
plSceneObject* pObj = plSceneObject::ConvertNoRef(light.getKey()->ObjectIsLoaded());
|
|
|
|
if (!pObj)
|
|
|
|
return;
|
|
|
|
|
|
|
|
plObjInterface* pIface = pObj->GetGenericInterface(plLightInfo::Index());
|
|
|
|
if (pIface)
|
|
|
|
{
|
|
|
|
// we are a light ourselves... are we the one they are looking for?
|
|
|
|
if (lightName != pObj->GetKeyName())
|
|
|
|
pIface = nil; // not the one they want, check our children
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!pIface)
|
|
|
|
{
|
|
|
|
// recurse through our children...
|
|
|
|
for (int i = 0; i < pObj->GetCoordinateInterface()->GetNumChildren(); i++)
|
|
|
|
{
|
|
|
|
const plSceneObject* child = pObj->GetCoordinateInterface()->GetChild(i)->GetOwner();
|
|
|
|
if (child)
|
|
|
|
{
|
|
|
|
pIface = child->GetGenericInterface(plLightInfo::Index());
|
|
|
|
if (pIface)
|
|
|
|
{
|
|
|
|
// found a child... is it the one we want?
|
|
|
|
if (lightName != child->GetKeyName())
|
|
|
|
pIface = nil; // not the child we want, keep looking
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (pIface)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (pIface)
|
|
|
|
{
|
|
|
|
plEnableMsg* enableMsg = new plEnableMsg;
|
|
|
|
enableMsg->AddReceiver(pIface->GetKey());
|
|
|
|
enableMsg->SetBCastFlag(plMessage::kNetPropagate);
|
|
|
|
enableMsg->SetBCastFlag(plMessage::kNetForce);
|
|
|
|
|
|
|
|
plAnimCmdMsg* animMsg = new plAnimCmdMsg;
|
|
|
|
animMsg->AddReceiver(pIface->GetOwnerKey());
|
|
|
|
animMsg->SetBCastFlag(plMessage::kPropagateToModifiers);
|
|
|
|
animMsg->SetBCastFlag(plMessage::kNetPropagate);
|
|
|
|
animMsg->SetBCastFlag(plMessage::kNetForce);
|
|
|
|
|
|
|
|
if (start)
|
|
|
|
{
|
|
|
|
enableMsg->SetCmd(plEnableMsg::kEnable);
|
|
|
|
animMsg->SetCmd(plAnimCmdMsg::kContinue);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
enableMsg->SetCmd(plEnableMsg::kDisable);
|
|
|
|
animMsg->SetCmd(plAnimCmdMsg::kStop);
|
|
|
|
animMsg->SetCmd(plAnimCmdMsg::kGoToBegin);
|
|
|
|
}
|
|
|
|
|
|
|
|
enableMsg->Send();
|
|
|
|
animMsg->Send();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Function : RegisterForControlEventMessages
|
|
|
|
// PARAMETERS : switch on or off, registrant
|
|
|
|
//
|
|
|
|
// PURPOSE : let you get control event messages at will (for pseudo-GUI's like the psnl bookshelf or clft imager)
|
|
|
|
|
|
|
|
void cyMisc::RegisterForControlEventMessages(hsBool on, pyKey& k)
|
|
|
|
{
|
|
|
|
plCmdIfaceModMsg* pMsg = new plCmdIfaceModMsg;
|
|
|
|
pMsg->SetSender(k.getKey());
|
|
|
|
if (on)
|
|
|
|
pMsg->SetCmd(plCmdIfaceModMsg::kAdd);
|
|
|
|
else
|
|
|
|
pMsg->SetCmd(plCmdIfaceModMsg::kRemove);
|
|
|
|
pMsg->SetBCastFlag(plMessage::kBCastByExactType);
|
|
|
|
pMsg->Send();
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Function : RequestLOSScreen
|
|
|
|
// PARAMETERS : lots...
|
|
|
|
//
|
|
|
|
// PURPOSE : To request an LOS from a point on the screen
|
|
|
|
//
|
|
|
|
#include "plMessage/plLOSRequestMsg.h"
|
|
|
|
bool cyMisc::RequestLOSScreen(pyKey &selfkey, int32_t ID, float xPos, float yPos, float distance, int what, int reportType)
|
|
|
|
{
|
|
|
|
plPipeline* pipe = selfkey.GetPipeline();
|
|
|
|
if (pipe)
|
|
|
|
{
|
|
|
|
int32_t x=(int32_t) ( xPos * pipe->Width() );
|
|
|
|
int32_t y=(int32_t) ( yPos * pipe->Height() );
|
|
|
|
|
|
|
|
hsPoint3 endPos, startPos;
|
|
|
|
|
|
|
|
pipe->ScreenToWorldPoint( 1,0, &x, &y, distance, 0, &endPos );
|
|
|
|
startPos = pipe->GetViewPositionWorld();
|
|
|
|
|
|
|
|
// move the start pos out a little to avoid backing up against physical objects...
|
|
|
|
hsVector3 view(endPos - startPos);
|
|
|
|
view.Normalize();
|
|
|
|
startPos = startPos + (view * 1.5f);
|
|
|
|
|
|
|
|
plLOSRequestMsg* pMsg = nil;
|
|
|
|
switch (what)
|
|
|
|
{
|
|
|
|
case kClickables:
|
|
|
|
pMsg = new plLOSRequestMsg( selfkey.getKey(), startPos, endPos, plSimDefs::kLOSDBUIItems, plLOSRequestMsg::kTestClosest );
|
|
|
|
pMsg->SetCullDB(plSimDefs::kLOSDBUIBlockers);
|
|
|
|
break;
|
|
|
|
case kCameraBlockers:
|
|
|
|
pMsg = new plLOSRequestMsg( selfkey.getKey(), startPos, endPos, plSimDefs::kLOSDBCameraBlockers, plLOSRequestMsg::kTestClosest );
|
|
|
|
break;
|
|
|
|
case kCustom:
|
|
|
|
pMsg = new plLOSRequestMsg( selfkey.getKey(), startPos, endPos, plSimDefs::kLOSDBCustom, plLOSRequestMsg::kTestClosest );
|
|
|
|
break;
|
|
|
|
case kShootable:
|
|
|
|
pMsg = new plLOSRequestMsg( selfkey.getKey(), startPos, endPos, plSimDefs::kLOSDBShootableItems, plLOSRequestMsg::kTestClosest );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( pMsg )
|
|
|
|
{
|
|
|
|
pMsg->SetReportType( (plLOSRequestMsg::ReportType)reportType );
|
|
|
|
|
|
|
|
pMsg->SetRequestID( ID );
|
|
|
|
|
|
|
|
plgDispatch::MsgSend( pMsg );
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Function : CheckVisLOS,CheckVisLOSFromCursor
|
|
|
|
// PARAMETERS : StartPoint, EndPoint
|
|
|
|
//
|
|
|
|
// PURPOSE : Check is there is something visible in the path from StartPoint to EndPoint
|
|
|
|
//
|
|
|
|
#include "plDrawable/plVisLOSMgr.h"
|
|
|
|
PyObject* cyMisc::CheckVisLOS(pyPoint3 startPoint, pyPoint3 endPoint)
|
|
|
|
{
|
|
|
|
if (plVisLOSMgr::Instance())
|
|
|
|
{
|
|
|
|
plVisHit hit;
|
|
|
|
if( plVisLOSMgr::Instance()->Check(startPoint.fPoint,endPoint.fPoint,hit) )
|
|
|
|
{
|
|
|
|
return pyPoint3::New(hit.fPos);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
PYTHON_RETURN_NONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
PyObject* cyMisc::CheckVisLOSFromCursor()
|
|
|
|
{
|
|
|
|
if (plVisLOSMgr::Instance())
|
|
|
|
{
|
|
|
|
plVisHit hit;
|
|
|
|
if( plVisLOSMgr::Instance()->CursorCheck(hit) )
|
|
|
|
{
|
|
|
|
return pyPoint3::New(hit.fPos);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
PYTHON_RETURN_NONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Function : IsSinglePlayerMode
|
|
|
|
// PARAMETERS :
|
|
|
|
//
|
|
|
|
// PURPOSE : Returns whether the game is in Single Player mode
|
|
|
|
//
|
|
|
|
bool cyMisc::IsSinglePlayerMode()
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Function : IsDemoMode
|
|
|
|
// PARAMETERS :
|
|
|
|
//
|
|
|
|
// PURPOSE : Returns whether the game is in Single Player mode
|
|
|
|
//
|
|
|
|
bool cyMisc::IsDemoMode()
|
|
|
|
{
|
|
|
|
plNetClientApp* nc = plNetClientApp::GetInstance();
|
|
|
|
if (nc)
|
|
|
|
return nc->InDemoMode();
|
|
|
|
// if we couldn't find the net client app, maybe it was because we are single player mode
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Function : IsInternalRelease
|
|
|
|
// PARAMETERS :
|
|
|
|
//
|
|
|
|
// PURPOSE : Returns true if we are running an internal build
|
|
|
|
//
|
|
|
|
bool cyMisc::IsInternalRelease()
|
|
|
|
{
|
|
|
|
#ifdef PLASMA_EXTERNAL_RELEASE
|
|
|
|
return false;
|
|
|
|
#else
|
|
|
|
return true;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Function : IsEnterChatModeKeyBound
|
|
|
|
// PARAMETERS :
|
|
|
|
//
|
|
|
|
// PURPOSE : Returns whether the EnterChatMode is bound to a key
|
|
|
|
//
|
|
|
|
bool cyMisc::IsEnterChatModeKeyBound()
|
|
|
|
{
|
|
|
|
plAvatarInputInterface* aii = plAvatarInputInterface::GetInstance();
|
|
|
|
if (aii)
|
|
|
|
return aii->IsEnterChatModeBound();
|
|
|
|
// if we couldn't find the net client app, maybe it was because we are single player mode
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Function : ShootBulletFromScreen
|
|
|
|
// PARAMETERS : lots...
|
|
|
|
//
|
|
|
|
// PURPOSE : Shoots from screen coordinates, a bullet and makes a mark on objects that know about bullet holes
|
|
|
|
//
|
|
|
|
#include "plMessage/plBulletMsg.h"
|
|
|
|
void cyMisc::ShootBulletFromScreen(pyKey &selfkey, float xPos, float yPos, float radius, float range)
|
|
|
|
{
|
|
|
|
plPipeline* pipe = selfkey.GetPipeline();
|
|
|
|
if (pipe)
|
|
|
|
{
|
|
|
|
int32_t x=(int32_t) ( xPos * pipe->Width() );
|
|
|
|
int32_t y=(int32_t) ( yPos * pipe->Height() );
|
|
|
|
|
|
|
|
hsPoint3 endPos, startPos;
|
|
|
|
|
|
|
|
pipe->ScreenToWorldPoint( 1,0, &x, &y, range, 0, &endPos );
|
|
|
|
startPos = pipe->GetViewPositionWorld();
|
|
|
|
|
|
|
|
// move the start pos out a little to avoid backing up against physical objects...
|
|
|
|
hsVector3 view(endPos - startPos);
|
|
|
|
view.Normalize();
|
|
|
|
startPos = startPos + (view * 1.5f);
|
|
|
|
|
|
|
|
plBulletMsg* bull = new plBulletMsg( selfkey.getKey(), nil, nil );
|
|
|
|
bull->FireShot(startPos, view, radius, range);
|
|
|
|
bull->Send();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Function : ShootBulletFromObject
|
|
|
|
// PARAMETERS : lots...
|
|
|
|
//
|
|
|
|
// PURPOSE : Shoots from an object, a bullet and makes a mark on objects that know about bullet holes
|
|
|
|
//
|
|
|
|
void cyMisc::ShootBulletFromObject(pyKey &selfkey, pySceneObject* sobj, float radius, float range)
|
|
|
|
{
|
|
|
|
plSceneObject* so = plSceneObject::ConvertNoRef(sobj->getObjKey()->ObjectIsLoaded());
|
|
|
|
if( so )
|
|
|
|
{
|
|
|
|
// find the direction
|
|
|
|
|
|
|
|
hsMatrix44 l2w = so->GetLocalToWorld();
|
|
|
|
hsVector3 dir(-l2w.fMap[0][0], -l2w.fMap[1][0], -l2w.fMap[2][0]);
|
|
|
|
dir.Normalize();
|
|
|
|
hsPoint3 pos = l2w.GetTranslate();
|
|
|
|
|
|
|
|
plBulletMsg* bull = new plBulletMsg(selfkey.getKey(), nil, nil);
|
|
|
|
bull->FireShot(pos, dir, radius, range);
|
|
|
|
|
|
|
|
bull->Send();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
class NetClientCommCallback : public plNetClientComm::Callback
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
enum Contexts
|
|
|
|
{
|
|
|
|
kInvalid,
|
|
|
|
kGetPublicAgeList,
|
|
|
|
kCreatePublicAge,
|
|
|
|
kRemovePublicAge,
|
|
|
|
};
|
|
|
|
|
|
|
|
PyObject * fPyObject;
|
|
|
|
NetClientCommCallback( PyObject * pyObject )
|
|
|
|
: fPyObject( pyObject )
|
|
|
|
{
|
|
|
|
Py_XINCREF( fPyObject );
|
|
|
|
}
|
|
|
|
~NetClientCommCallback()
|
|
|
|
{
|
|
|
|
Py_XDECREF( fPyObject );
|
|
|
|
}
|
|
|
|
void OperationStarted( uint32_t context )
|
|
|
|
{}
|
|
|
|
void OperationComplete( uint32_t context, int resultCode )
|
|
|
|
{
|
|
|
|
if ( !fPyObject )
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PyObject* func = nil;
|
|
|
|
|
|
|
|
switch ( context )
|
|
|
|
{
|
|
|
|
case kGetPublicAgeList:
|
|
|
|
// Call the callback.
|
|
|
|
func = PyObject_GetAttrString( fPyObject, "gotPublicAgeList" );
|
|
|
|
if ( func )
|
|
|
|
{
|
|
|
|
if ( PyCallable_Check(func)>0 )
|
|
|
|
{
|
|
|
|
plCreatableStream * ageInfoStream = plCreatableStream::ConvertNoRef( fCbArgs.GetItem( 0 ) );
|
|
|
|
plCreatableStream * nPlayersStream = plCreatableStream::ConvertNoRef( fCbArgs.GetItem( 1 ) );
|
|
|
|
|
|
|
|
if ( ageInfoStream && nPlayersStream )
|
|
|
|
{
|
|
|
|
uint16_t nAgeInfoEntries;
|
|
|
|
ageInfoStream->GetStream()->ReadLE( &nAgeInfoEntries );
|
|
|
|
|
|
|
|
uint16_t nPlayerCountEntries;
|
|
|
|
nPlayersStream->GetStream()->ReadLE( &nPlayerCountEntries );
|
|
|
|
|
|
|
|
hsAssert( nAgeInfoEntries==nPlayerCountEntries, "huh?" );
|
|
|
|
|
|
|
|
// convert callback args to a list of tuple(ageInfo,nPlayers)
|
|
|
|
PyObject* pyEL = PyList_New(nAgeInfoEntries);
|
|
|
|
|
|
|
|
for ( int i=0; i<nAgeInfoEntries; i++ )
|
|
|
|
{
|
|
|
|
plAgeInfoStruct ageInfo;
|
|
|
|
uint32_t nPlayers;
|
|
|
|
ageInfo.Read( ageInfoStream->GetStream(), nil );
|
|
|
|
nPlayersStream->GetStream()->ReadLE( &nPlayers );
|
|
|
|
PyObject* t = PyTuple_New(2);
|
|
|
|
PyTuple_SetItem(t, 0, pyAgeInfoStruct::New(&ageInfo));
|
|
|
|
PyTuple_SetItem(t, 1, PyLong_FromUnsignedLong(nPlayers));
|
|
|
|
PyList_SetItem(pyEL, i, t); // steals the ref
|
|
|
|
}
|
|
|
|
PyObject* retVal = PyObject_CallMethod(fPyObject, "gotPublicAgeList", "O", pyEL);
|
|
|
|
Py_XDECREF(retVal);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case kCreatePublicAge:
|
|
|
|
// Call the callback.
|
|
|
|
func = PyObject_GetAttrString( fPyObject, "publicAgeCreated" );
|
|
|
|
if ( func )
|
|
|
|
{
|
|
|
|
if ( PyCallable_Check(func)>0 )
|
|
|
|
{
|
|
|
|
plAgeInfoStruct * ageInfo = plAgeInfoStruct::ConvertNoRef( fCbArgs.GetItem( 0 ) );
|
|
|
|
|
|
|
|
if ( ageInfo )
|
|
|
|
{
|
|
|
|
PyObject* ageInfoObj = pyAgeInfoStruct::New(ageInfo);
|
|
|
|
PyObject* retVal = PyObject_CallMethod(fPyObject, "publicAgeCreated", "O", ageInfoObj);
|
|
|
|
Py_XDECREF(retVal);
|
|
|
|
Py_DECREF(ageInfoObj);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case kRemovePublicAge:
|
|
|
|
// Call the callback.
|
|
|
|
func = PyObject_GetAttrString( fPyObject, "publicAgeRemoved" );
|
|
|
|
if ( func )
|
|
|
|
{
|
|
|
|
if ( PyCallable_Check(func)>0 )
|
|
|
|
{
|
|
|
|
plCreatableUuid * guid = plCreatableUuid::ConvertNoRef( fCbArgs.GetItem( 0 ) );
|
|
|
|
|
|
|
|
if ( guid )
|
|
|
|
{
|
|
|
|
PyObject* retVal = PyObject_CallMethod(fPyObject, "publicAgeRemoved", "s", guid->AsString().c_str());
|
|
|
|
Py_XDECREF(retVal);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
delete this;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Function : GetPublicAgeList
|
|
|
|
// PARAMETERS : ageName, callback object
|
|
|
|
//
|
|
|
|
// PURPOSE : Get the list of public ages for the given age name.
|
|
|
|
//
|
|
|
|
void cyMisc::GetPublicAgeList( const char * ageName, PyObject * cbObject )
|
|
|
|
{
|
|
|
|
if (cbObject)
|
|
|
|
Py_XINCREF(cbObject);
|
|
|
|
NetCommGetPublicAgeList(
|
|
|
|
ageName,
|
|
|
|
cbObject,
|
|
|
|
plNetCommReplyMsg::kParamTypePython
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Function : CreatePublicAge
|
|
|
|
// PARAMETERS : ageInfo, callback object
|
|
|
|
//
|
|
|
|
// PURPOSE : Add a public age to the list of available ones.
|
|
|
|
//
|
|
|
|
void cyMisc::CreatePublicAge( pyAgeInfoStruct * ageInfo, PyObject * cbObject )
|
|
|
|
{
|
|
|
|
VaultSetOwnedAgePublicAndWait(ageInfo->GetAgeInfo(), true);
|
|
|
|
// TODO: make the callback here
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Function : RemovePublicAge
|
|
|
|
// PARAMETERS : ageInstanceGuid, callback object
|
|
|
|
//
|
|
|
|
// PURPOSE : Remove a public age from the list of available ones.
|
|
|
|
//
|
|
|
|
void cyMisc::RemovePublicAge( const char * ageInstanceGuid, PyObject * cbObject/*=nil */)
|
|
|
|
{
|
|
|
|
plAgeInfoStruct info;
|
|
|
|
plUUID uuid(ageInstanceGuid);
|
|
|
|
info.SetAgeInstanceGuid(&uuid);
|
|
|
|
VaultSetOwnedAgePublicAndWait(&info, false);
|
|
|
|
// TODO: make the callback here
|
|
|
|
}
|
|
|
|
|
|
|
|
int cyMisc::GetKILevel()
|
|
|
|
{
|
|
|
|
int result = pfKIMsg::kNanoKI;
|
|
|
|
|
|
|
|
wchar_t wStr[MAX_PATH];
|
|
|
|
StrToUnicode(wStr, pfKIMsg::kChronicleKILevel, arrsize(wStr));
|
|
|
|
if (RelVaultNode * rvn = VaultFindChronicleEntryIncRef(wStr)) {
|
|
|
|
VaultChronicleNode chron(rvn);
|
|
|
|
result = wcstol(chron.entryValue, nil, 0);
|
|
|
|
rvn->DecRef();
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// the following are for recording and rebuilding the camera stack
|
|
|
|
|
|
|
|
#include "pfCamera/plCameraModifier.h"
|
|
|
|
|
|
|
|
int cyMisc::GetNumCameras()
|
|
|
|
{
|
|
|
|
return (plVirtualCam1::Instance()->GetNumCameras());
|
|
|
|
}
|
|
|
|
|
|
|
|
const char* cyMisc::GetCameraNumber(int number)
|
|
|
|
{
|
|
|
|
plCameraModifier1* pCam = plVirtualCam1::Instance()->GetCameraNumber(number-1);
|
|
|
|
if (pCam->GetTarget())
|
|
|
|
{
|
|
|
|
const char* ret = pCam->GetTarget()->GetKeyName().c_str();
|
|
|
|
plString str = plString::Format("saving camera named %s to chronicle\n",ret);
|
|
|
|
plVirtualCam1::Instance()->AddMsgToLog(str.c_str());
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
plVirtualCam1::Instance()->AddMsgToLog("sending empty to camera chronicle\n");
|
|
|
|
return "empty";
|
|
|
|
}
|
|
|
|
|
|
|
|
void cyMisc::RebuildCameraStack(const plString& name, const char* ageName)
|
|
|
|
{
|
|
|
|
plKey key=nil;
|
|
|
|
plString str = plString::Format("attempting to restore camera named %s from chronicle\n",name.c_str());
|
|
|
|
plVirtualCam1::Instance()->AddMsgToLog(str.c_str());
|
|
|
|
|
|
|
|
if (name.Compare("empty") == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if ( !name.IsEmpty() )
|
|
|
|
{
|
|
|
|
key=plKeyFinder::Instance().StupidSearch(nil,nil,plSceneObject::Index(), name, false);
|
|
|
|
}
|
|
|
|
if ( key == nil )
|
|
|
|
{
|
|
|
|
// try and use this new hack method to find it
|
|
|
|
if (!plVirtualCam1::Instance()->RestoreFromName(name))
|
|
|
|
{
|
|
|
|
// give up and force built in 3rd person
|
|
|
|
plVirtualCam1::Instance()->PushThirdPerson();
|
|
|
|
plString errmsg = plString::Format("Sceneobject %s not found",name.c_str());
|
|
|
|
PyErr_SetString(PyExc_NameError, errmsg.c_str());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// now we have the scene object, look for it's camera modifier
|
|
|
|
const plCameraModifier1* pMod = nil;
|
|
|
|
plSceneObject* pObj = plSceneObject::ConvertNoRef(key->ObjectIsLoaded());
|
|
|
|
if (pObj)
|
|
|
|
{
|
|
|
|
for (int i = 1; i < pObj->GetNumModifiers(); i++)
|
|
|
|
{
|
|
|
|
pMod = plCameraModifier1::ConvertNoRef(pObj->GetModifier(i));
|
|
|
|
if (pMod)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (pMod)
|
|
|
|
{
|
|
|
|
plVirtualCam1::Instance()->RebuildStack(pMod->GetKey());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
plVirtualCam1::Instance()->PushThirdPerson();
|
|
|
|
plString errmsg = plString::Format("Sceneobject %s has no camera modifier",name.c_str());
|
|
|
|
PyErr_SetString(PyExc_NameError, errmsg.c_str());
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void cyMisc::PyClearCameraStack()
|
|
|
|
{
|
|
|
|
plVirtualCam1::Instance()->ClearStack();
|
|
|
|
}
|
|
|
|
|
|
|
|
void cyMisc::RecenterCamera()
|
|
|
|
{
|
|
|
|
plCameraMsg* pCam = new plCameraMsg;
|
|
|
|
pCam->SetBCastFlag(plMessage::kBCastByExactType);
|
|
|
|
pCam->SetCmd(plCameraMsg::kResetPanning);
|
|
|
|
pCam->Send();
|
|
|
|
}
|
|
|
|
|
|
|
|
#include "plMessage/plTransitionMsg.h"
|
|
|
|
|
|
|
|
void cyMisc::FadeIn(float lenTime, bool holdFlag, bool noSound)
|
|
|
|
{
|
|
|
|
plTransitionMsg *msg = new plTransitionMsg( noSound ? plTransitionMsg::kFadeInNoSound : plTransitionMsg::kFadeIn, lenTime, holdFlag );
|
|
|
|
plgDispatch::MsgSend( msg );
|
|
|
|
}
|
|
|
|
|
|
|
|
void cyMisc::FadeOut(float lenTime, bool holdFlag, bool noSound)
|
|
|
|
{
|
|
|
|
plTransitionMsg *msg = new plTransitionMsg( noSound ? plTransitionMsg::kFadeOutNoSound : plTransitionMsg::kFadeOut, lenTime, holdFlag );
|
|
|
|
plgDispatch::MsgSend( msg );
|
|
|
|
}
|
|
|
|
|
|
|
|
void cyMisc::SetClickability(hsBool b)
|
|
|
|
{
|
|
|
|
plInputIfaceMgrMsg* msg = new plInputIfaceMgrMsg(b ? plInputIfaceMgrMsg::kEnableClickables : plInputIfaceMgrMsg::kDisableClickables );
|
|
|
|
plgDispatch::MsgSend(msg);
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Function : Debug build only: Assert if condition is false.
|
|
|
|
//
|
|
|
|
// PURPOSE : debugging
|
|
|
|
//
|
|
|
|
void cyMisc::DebugAssert( bool cond, const char * msg )
|
|
|
|
{
|
|
|
|
hsAssert( cond, msg );
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Function : Set a python object to be called back after a certain amount of time.
|
|
|
|
//
|
|
|
|
// PURPOSE : script can trigger itself over time w/o having to specify it in the dataset.
|
|
|
|
//
|
|
|
|
void cyMisc::SetAlarm( float secs, PyObject * cb, uint32_t cbContext )
|
|
|
|
{
|
|
|
|
pyAlarmMgr::GetInstance()->SetAlarm( secs, cb, cbContext );
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Function : Save Screen Shot
|
|
|
|
//
|
|
|
|
// PURPOSE : captures the screen and saves it as a jpeg
|
|
|
|
//
|
|
|
|
#include "plJPEG/plJPEG.h"
|
|
|
|
void cyMisc::SaveScreenShot(const char* fileName, int x, int y, int quality)
|
|
|
|
{
|
|
|
|
if ( cyMisc::GetPipeline() )
|
|
|
|
{
|
|
|
|
if (quality <= 0 || quality > 100)
|
|
|
|
quality = 75;
|
|
|
|
|
|
|
|
plMipmap mipmap;
|
|
|
|
cyMisc::GetPipeline()->CaptureScreen( &mipmap, false, x, y );
|
|
|
|
|
|
|
|
plJPEG::Instance().SetWriteQuality( quality );
|
|
|
|
plJPEG::Instance().WriteToFile( fileName, &mipmap );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Function : Start a screen capture
|
|
|
|
//
|
|
|
|
// PURPOSE : This starts a screen capture in motion. It will be capture on the next
|
|
|
|
// update and a plCaptureRenderMsg when its ready
|
|
|
|
//
|
|
|
|
#include "plPipeline/plCaptureRender.h"
|
|
|
|
void cyMisc::StartScreenCapture(pyKey& selfkey)
|
|
|
|
{
|
|
|
|
cyMisc::StartScreenCaptureWH(selfkey, 800, 600);
|
|
|
|
}
|
|
|
|
|
|
|
|
void cyMisc::StartScreenCaptureWH(pyKey& selfkey, uint16_t width, uint16_t height)
|
|
|
|
{
|
|
|
|
plCaptureRender::Capture(selfkey.getKey(), width, height);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#include "plAvatar/plAvatarClothing.h"
|
|
|
|
void cyMisc::WearMaintainerSuit(pyKey& key, hsBool wear)
|
|
|
|
{
|
|
|
|
// run on all machines, but only affects us if we call it on our local guy (who props it to others himself)
|
|
|
|
if (key.getKey() != plNetClientMgr::GetInstance()->GetLocalPlayerKey())
|
|
|
|
return;
|
|
|
|
|
|
|
|
plArmatureMod *avMod = plAvatarMgr::GetInstance()->GetLocalAvatar();
|
|
|
|
|
|
|
|
if (avMod)
|
|
|
|
{
|
|
|
|
if (wear)
|
|
|
|
avMod->GetClothingOutfit()->WearMaintainerOutfit();
|
|
|
|
else
|
|
|
|
avMod->GetClothingOutfit()->RemoveMaintainerOutfit();
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void cyMisc::WearDefaultClothing(pyKey& key)
|
|
|
|
{
|
|
|
|
if (key.getKey() != plNetClientMgr::GetInstance()->GetLocalPlayerKey())
|
|
|
|
return;
|
|
|
|
|
|
|
|
plArmatureMod *avMod = plAvatarMgr::GetInstance()->GetLocalAvatar();
|
|
|
|
|
|
|
|
if (avMod)
|
|
|
|
{
|
|
|
|
avMod->GetClothingOutfit()->WearDefaultClothing();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void cyMisc::WearDefaultClothingType(pyKey& key, uint32_t type)
|
|
|
|
{
|
|
|
|
if (key.getKey() != plNetClientMgr::GetInstance()->GetLocalPlayerKey())
|
|
|
|
return;
|
|
|
|
|
|
|
|
plArmatureMod *avMod = plAvatarMgr::GetInstance()->GetLocalAvatar();
|
|
|
|
|
|
|
|
if (avMod)
|
|
|
|
{
|
|
|
|
avMod->GetClothingOutfit()->WearDefaultClothingType(type);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Function : Fake link to object
|
|
|
|
//
|
|
|
|
// PURPOSE : takes an avatar key and an object key and fake-links the avatar
|
|
|
|
// to that object's position. appears to be a link to other players
|
|
|
|
//
|
|
|
|
|
|
|
|
void cyMisc::FakeLinkToObject(pyKey& avatar, pyKey& object)
|
|
|
|
{
|
|
|
|
plPseudoLinkEffectMsg* msg = new plPseudoLinkEffectMsg;
|
|
|
|
msg->fAvatarKey = avatar.getKey();
|
|
|
|
msg->fLinkObjKey = object.getKey();
|
|
|
|
plgDispatch::MsgSend(msg);
|
|
|
|
}
|
|
|
|
|
|
|
|
void cyMisc::FakeLinkToObjectNamed(const plString& name)
|
|
|
|
{
|
|
|
|
plKey key = nil;
|
|
|
|
if ( !name.IsEmpty() )
|
|
|
|
{
|
|
|
|
key = plKeyFinder::Instance().StupidSearch(nil,nil,plSceneObject::Index(), name, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!key)
|
|
|
|
return;
|
|
|
|
plPseudoLinkEffectMsg* msg = new plPseudoLinkEffectMsg;
|
|
|
|
msg->fAvatarKey = plNetClientMgr::GetInstance()->GetLocalPlayerKey();
|
|
|
|
msg->fLinkObjKey = key;
|
|
|
|
plgDispatch::MsgSend(msg);
|
|
|
|
}
|
|
|
|
|
|
|
|
PyObject* cyMisc::LoadAvatarModel(const char* modelName, pyKey& spawnPoint, const char* userStr)
|
|
|
|
{
|
|
|
|
plKey SpawnedKey = plAvatarMgr::GetInstance()->LoadAvatar(modelName, "", false, spawnPoint.getKey(), nil, userStr);
|
|
|
|
return pyKey::New(SpawnedKey);
|
|
|
|
}
|
|
|
|
|
|
|
|
void cyMisc::UnLoadAvatarModel(pyKey& avatar)
|
|
|
|
{
|
|
|
|
plAvatarMgr::GetInstance()->UnLoadAvatar(avatar.getKey(), false);
|
|
|
|
}
|
|
|
|
|
|
|
|
void cyMisc::ForceCursorHidden()
|
|
|
|
{
|
|
|
|
plMouseDevice::HideCursor(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
void cyMisc::ForceCursorShown()
|
|
|
|
{
|
|
|
|
plMouseDevice::ShowCursor(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Function : GetLocalizedString
|
|
|
|
//
|
|
|
|
// PURPOSE : Returns the specified localized string with the parameters
|
|
|
|
// properly replaced (the list is a list of unicode strings) Name
|
|
|
|
// is in "Age.Set.Name" format
|
|
|
|
//
|
|
|
|
std::wstring cyMisc::GetLocalizedString(std::wstring name, const std::vector<std::wstring> & arguments)
|
|
|
|
{
|
|
|
|
if (pfLocalizationMgr::InstanceValid())
|
|
|
|
return pfLocalizationMgr::Instance().GetString(name, arguments);
|
|
|
|
return L"";
|
|
|
|
}
|
|
|
|
|
|
|
|
void cyMisc::EnablePlanarReflections(bool enable)
|
|
|
|
{
|
|
|
|
plDynamicCamMap::SetEnabled(enable);
|
|
|
|
}
|
|
|
|
|
|
|
|
void cyMisc::GetSupportedDisplayModes(std::vector<plDisplayMode> *res)
|
|
|
|
{
|
|
|
|
fPipeline->GetSupportedDisplayModes(res);
|
|
|
|
}
|
|
|
|
|
|
|
|
int cyMisc::GetDesktopWidth()
|
|
|
|
{
|
|
|
|
return fPipeline->GetDesktopWidth();
|
|
|
|
}
|
|
|
|
|
|
|
|
int cyMisc::GetDesktopHeight()
|
|
|
|
{
|
|
|
|
return fPipeline->GetDesktopHeight();
|
|
|
|
}
|
|
|
|
|
|
|
|
int cyMisc::GetDesktopColorDepth()
|
|
|
|
{
|
|
|
|
return fPipeline->GetDesktopColorDepth();
|
|
|
|
}
|
|
|
|
|
|
|
|
PipelineParams *cyMisc::GetDefaultDisplayParams()
|
|
|
|
{
|
|
|
|
return fPipeline->GetDefaultParams();
|
|
|
|
}
|
|
|
|
|
|
|
|
void cyMisc::SetGraphicsOptions(int Width, int Height, int ColorDepth, hsBool Windowed, int NumAASamples, int MaxAnisotropicSamples, hsBool VSync)
|
|
|
|
{
|
|
|
|
// This has to send a message to plClient because python is loaded in the max plugins
|
|
|
|
|
|
|
|
plKey clientKey = hsgResMgr::ResMgr()->FindKey( kClient_KEY );
|
|
|
|
plClientMsg* clientMsg = new plClientMsg(plClientMsg::kResetGraphicsDevice);
|
|
|
|
clientMsg->AddReceiver(clientKey);
|
|
|
|
//clientMsg->SetBCastFlag(plMessage::kBCastByType);
|
|
|
|
clientMsg->fGraphicsSettings.fWidth = Width;
|
|
|
|
clientMsg->fGraphicsSettings.fHeight = Height;
|
|
|
|
clientMsg->fGraphicsSettings.fColorDepth = ColorDepth;
|
|
|
|
clientMsg->fGraphicsSettings.fWindowed = Windowed;
|
|
|
|
clientMsg->fGraphicsSettings.fNumAASamples = NumAASamples;
|
|
|
|
clientMsg->fGraphicsSettings.fMaxAnisoSamples = MaxAnisotropicSamples;
|
|
|
|
clientMsg->fGraphicsSettings.fVSync = VSync;
|
|
|
|
clientMsg->Send();
|
|
|
|
|
|
|
|
//plClient::GetInstance()->ResetDisplayDevice(Width, Height, ColorDepth, Windowed, NumAASamples, MaxAnisotropicSamples);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool cyMisc::DumpLogs(const std::wstring & folder)
|
|
|
|
{
|
|
|
|
char* temp = hsWStringToString(folder.c_str());
|
|
|
|
bool retVal = plStatusLogMgr::GetInstance().DumpLogs(temp);
|
|
|
|
delete [] temp;
|
|
|
|
return retVal;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool cyMisc::FileExists(const std::wstring & filename)
|
|
|
|
{
|
|
|
|
return PathDoesFileExist(filename.c_str());
|
|
|
|
}
|
|
|
|
|
|
|
|
bool cyMisc::CreateDir(const std::wstring & directory)
|
|
|
|
{
|
|
|
|
return PathCreateDirectory(directory.c_str(), kPathCreateDirFlagEntireTree) == kPathCreateDirSuccess;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::wstring cyMisc::GetUserPath()
|
|
|
|
{
|
|
|
|
wchar_t path[MAX_PATH];
|
|
|
|
PathGetUserDirectory(path, arrsize(path));
|
|
|
|
return path;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::wstring cyMisc::GetInitPath()
|
|
|
|
{
|
|
|
|
wchar_t path[MAX_PATH];
|
|
|
|
PathGetInitDirectory(path, arrsize(path));
|
|
|
|
return path;
|
|
|
|
}
|
|
|
|
|
|
|
|
void cyMisc::SetBehaviorNetFlags(pyKey & behKey, hsBool netForce, hsBool netProp)
|
|
|
|
{
|
|
|
|
if (plMultistageBehMod * behMod = plMultistageBehMod::ConvertNoRef(behKey.getKey()->ObjectIsLoaded()))
|
|
|
|
{
|
|
|
|
behMod->SetNetForce(netForce);
|
|
|
|
behMod->SetNetProp(netProp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void cyMisc::SendFriendInvite(const wchar_t email[], const wchar_t toName[])
|
|
|
|
{
|
|
|
|
if (RelVaultNode* pNode = VaultGetPlayerNodeIncRef())
|
|
|
|
{
|
|
|
|
VaultPlayerNode player(pNode);
|
|
|
|
Uuid inviteUuid = player.inviteUuid;
|
|
|
|
|
|
|
|
// If we don't have an invite UUID set then make a new one
|
|
|
|
if (GuidIsNil(inviteUuid))
|
|
|
|
{
|
|
|
|
inviteUuid = GuidGenerate();
|
|
|
|
player.SetInviteUuid(inviteUuid);
|
|
|
|
}
|
|
|
|
|
|
|
|
NetCommSendFriendInvite(email, toName, inviteUuid);
|
|
|
|
pNode->DecRef();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
PyObject* cyMisc::PyGuidGenerate()
|
|
|
|
{
|
|
|
|
char guidStr[64];
|
|
|
|
Uuid newGuid = GuidGenerate();
|
|
|
|
GuidToString(newGuid, guidStr, arrsize(guidStr));
|
|
|
|
|
|
|
|
return PyString_FromString(guidStr);
|
|
|
|
}
|
|
|
|
|
|
|
|
PyObject* cyMisc::GetAIAvatarsByModelName(const char* name)
|
|
|
|
{
|
|
|
|
plAvatarMgr::plArmatureModPtrVec armVec;
|
|
|
|
plAvatarMgr::GetInstance()->FindAllAvatarsByModelName(name, armVec);
|
|
|
|
|
|
|
|
PyObject* avList = PyList_New(0);
|
|
|
|
|
|
|
|
for (plAvatarMgr::plArmatureModPtrVec::iterator it = armVec.begin(); it != armVec.end(); ++it)
|
|
|
|
{
|
|
|
|
plArmatureMod* armMod = (*it);
|
|
|
|
plAvBrainCritter* critterBrain = plAvBrainCritter::ConvertNoRef(armMod->FindBrainByClass(plAvBrainCritter::Index()));
|
|
|
|
if (critterBrain)
|
|
|
|
{
|
|
|
|
PyObject* tuple = PyTuple_New(2);
|
|
|
|
PyTuple_SetItem(tuple, 0, pyCritterBrain::New(critterBrain));
|
|
|
|
PyTuple_SetItem(tuple, 1, PyString_FromString(armMod->GetUserStr()));
|
|
|
|
|
|
|
|
PyList_Append(avList, tuple);
|
|
|
|
Py_DECREF(tuple);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (PyList_Size(avList) > 0)
|
|
|
|
return avList;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Py_DECREF(avList);
|
|
|
|
PYTHON_RETURN_NONE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void cyMisc::ForceVaultNodeUpdate(unsigned nodeId)
|
|
|
|
{
|
|
|
|
VaultFetchNodesAndWait(&nodeId, 1, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
void cyMisc::VaultDownload(unsigned nodeId)
|
|
|
|
{
|
|
|
|
VaultDownloadAndWait(
|
|
|
|
L"PyVaultDownload",
|
|
|
|
nodeId,
|
|
|
|
nil,
|
|
|
|
nil
|
|
|
|
);
|
|
|
|
}
|