You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2840 lines
85 KiB

/*==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/>.
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 "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 cyMisc::fUniqueNumber = 0;
#ifdef PLASMA_EXTERNAL_RELEASE
UInt32 cyMisc::fPythonLoggingLevel = cyMisc::kErrorLevel;
#else
UInt32 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 cyMisc::GetPythonLoggingLevel()
{
return fPythonLoggingLevel;
}
void cyMisc::SetPythonLoggingLevel(UInt32 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 = TRACKED_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 = TRACKED_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 char* name, const char* ageName)
{
// assume that we won't find the sceneobject (key is equal to nil)
plKey key=nil;
if ( name || name[0] != 0)
{
const char* theAge = ageName;
if ( ageName[0] == 0 )
theAge = nil;
key=plKeyFinder::Instance().StupidSearch(theAge,nil,plSceneObject::Index(), name, false);
}
if ( key == nil )
{
char errmsg[256];
sprintf(errmsg,"Sceneobject %s not found",name);
PyErr_SetString(PyExc_NameError, errmsg);
return nil; // return nil cause we errored
}
return pySceneObject::New(key);
}
PyObject* cyMisc::FindActivator(const char* name)
{
plKey key = nil;
if (name && strlen(name) > 0)
{
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 = TRACKED_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 = TRACKED_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, hsScalar time, UInt32 id)
{
// setup the message to come back to whoever the pyKey is pointing to
plTimerCallbackMsg* pTimerMsg = TRACKED_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 = TRACKED_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 = TRACKED_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 = TRACKED_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 = TRACKED_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 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 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.
//
const char* cyMisc::GetClientName(pyKey &avKey)
{
const char* ret=plNetClientMgr::GetInstance()->GetPlayerName(avKey.getKey());
return (ret==nil) ? "" : ret;
}
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
//
const char* 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 cyMisc::GetAgeTime( void )
{
return VaultAgeGetAgeTime();
}
UInt32 cyMisc::GetDniTime(void)
{
const plUnifiedTime utime = plNetClientMgr::GetInstance()->GetServerTime();
if ( utime.GetSecs() != 0)
return ConvertGMTtoDni(utime.GetSecs());
else
return 0;
}
UInt32 cyMisc::GetServerTime(void)
{
const plUnifiedTime utime = plNetClientMgr::GetInstance()->GetServerTime();
return utime.GetSecs();
}
float cyMisc::GetAgeTimeOfDayPercent(void)
{
return plNetClientMgr::GetInstance()->GetCurrentAgeTimeOfDayPercent();
}
#define kMST (UInt32)25200
#define kOneHour (UInt32)3600
#define kOneDay (UInt32)86400
UInt32 cyMisc::ConvertGMTtoDni(UInt32 gtime)
{
// convert to mountain time
UInt32 dtime = gtime - kMST;
plUnifiedTime utime = plUnifiedTime();
utime.SetSecs(dtime);
// check for daylight savings time in New Mexico and adjust
if ( utime.GetMonth() >= 4 && utime.GetMonth() < 11 )
{
plUnifiedTime dstStart = plUnifiedTime();
dstStart.SetGMTime(utime.GetYear(),4,1,2,0,0);
// find first Sunday after 4/1 (first sunday of April)
UInt32 days_to_go = 7 - dstStart.GetDayOfWeek();
if (days_to_go == 7)
days_to_go = 0;
UInt32 dstStartSecs = dstStart.GetSecs() + days_to_go * kOneDay;
plUnifiedTime dstEnd = plUnifiedTime();
dstEnd.SetGMTime(utime.GetYear(),10,25,1,0,0);
// find first sunday after 10/25 (last sunday of Oct.)
days_to_go = 7 - dstEnd.GetDayOfWeek();
if (days_to_go == 7)
days_to_go = 0;
UInt32 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 state)
{
plExcludeRegionMsg *msg = TRACKED_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 state)
{
plExcludeRegionMsg *msg = TRACKED_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
}
#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
//
hsScalar 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 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(),
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(), 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(), 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 cyMisc::GetMaxListenListSize()
{
return plNetListenList::kMaxListenListSize;
}
hsScalar 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 cyMisc::SendRTChat(pyPlayer& from, const std::vector<pyPlayer*> & tolist, const char* message, UInt32 flags)
{
// create the messge that will contain the chat message
pfKIMsg *msg = TRACKED_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 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 command, hsScalar value)
{
// create the mesage to send
pfKIMsg *msg = TRACKED_NEW pfKIMsg( (UInt8)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 command, const wchar_t* value)
{
// create the mesage to send
pfKIMsg *msg = TRACKED_NEW pfKIMsg( (UInt8)command );
msg->SetString( value );
// send it off
plgDispatch::MsgSend( msg );
}
/////////////////////////////////////////////////////////////////////////////
//
// Function : SendKIMessageI
// PARAMETERS : command - the command type
// : value - extra value as an Int32
//
// PURPOSE : Send message to the KI, to tell it things to do
//
// RETURNS : nothing
//
void cyMisc::SendKIMessageI(UInt32 command, Int32 value)
{
// create the mesage to send
pfKIMsg *msg = TRACKED_NEW pfKIMsg( (UInt8)command );
msg->SetIntValue(value);
// send it off
plgDispatch::MsgSend( msg );
}
/////////////////////////////////////////////////////////////////////////////
//
// Function : SendKIMessageIReply
// PARAMETERS : command - the command type
// : value - extra value as an Int32
//
// PURPOSE : Send message to the KI, to tell it things to do
//
// RETURNS : nothing
//
void cyMisc::SendKIGZMarkerMsg(Int32 markerNumber, pyKey& sender)
{
// create the mesage to send
pfKIMsg *msg = TRACKED_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 = TRACKED_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 = TRACKED_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 = TRACKED_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 = TRACKED_NEW plNetVoiceListMsg(plNetVoiceListMsg::kForcedListenerMode);
for (int i=0 ; i<tolist.size() ; i++ )
pMsg->GetClientList()->Append(tolist[i]->GetPlayerID());
pMsg->SetRemovedKey(plNetClientMgr::GetInstance()->GetLocalPlayerKey());
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 = TRACKED_NEW plNetVoiceListMsg(plNetVoiceListMsg::kDistanceMode);
pMsg->SetRemovedKey( member.getKey() );
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 reason,const char* title)
{
// create the mesage to send
plCCRPetitionMsg *msg = TRACKED_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 CCRPlayerID)
{
// create the mesage to send
plCCRCommunicationMsg *msg = TRACKED_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 = TRACKED_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 = TRACKED_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 = TRACKED_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 = TRACKED_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 = TRACKED_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 = TRACKED_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 = TRACKED_NEW plInputIfaceMgrMsg(plInputIfaceMgrMsg::kSetOfferBookMode);
pMsg->SetSender(selfkey.getKey());
pMsg->SetAgeFileName(ageFilename);
pMsg->SetAgeName(ageInstanceName);
pMsg->Send();
}
void cyMisc::DisableOfferBookMode()
{
plInputIfaceMgrMsg* pMsg = TRACKED_NEW plInputIfaceMgrMsg(plInputIfaceMgrMsg::kClearOfferBookMode);
pMsg->Send();
}
void cyMisc::NotifyOffererPublicLinkCompleted(UInt32 offerer)
{
plInputIfaceMgrMsg* pMsg = TRACKED_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 offerer)
{
plInputIfaceMgrMsg* pMsg = TRACKED_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 offerer)
{
plInputIfaceMgrMsg* pMsg = TRACKED_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 = TRACKED_NEW plInputIfaceMgrMsg(plInputIfaceMgrMsg::kGUIEnableAvatarClickable);
else
pMsg = TRACKED_NEW plInputIfaceMgrMsg(plInputIfaceMgrMsg::kGUIDisableAvatarClickable);
pMsg->SetAvKey(plNetClientMgr::GetInstance()->GetLocalPlayerKey());
pMsg->SetBCastFlag(plMessage::kNetPropagate);
pMsg->SetBCastFlag(plMessage::kNetForce);
pMsg->Send();
}
void cyMisc::SetShareSpawnPoint(const char* spawnPoint)
{
plInputIfaceMgrMsg* pMsg = TRACKED_NEW plInputIfaceMgrMsg(plInputIfaceMgrMsg::kSetShareSpawnPoint);
pMsg->SetSender(plNetClientMgr::GetInstance()->GetLocalPlayerKey());
pMsg->SetSpawnPoint(spawnPoint);
pMsg->Send();
}
void cyMisc::SetShareAgeInstanceGuid(const Uuid& guid)
{
plInputIfaceMgrMsg* pMsg = TRACKED_NEW plInputIfaceMgrMsg(plInputIfaceMgrMsg::kSetShareAgeInstanceGuid);
pMsg->SetSender(plNetClientMgr::GetInstance()->GetLocalPlayerKey());
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 = TRACKED_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)
{
(TRACKED_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)
{
(TRACKED_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 = TRACKED_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, std::string lightName, hsScalar r, hsScalar g, hsScalar b, hsScalar 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, std::string 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 = TRACKED_NEW plEnableMsg;
enableMsg->AddReceiver(pIface->GetKey());
enableMsg->SetBCastFlag(plMessage::kNetPropagate);
enableMsg->SetBCastFlag(plMessage::kNetForce);
plAnimCmdMsg* animMsg = TRACKED_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 = TRACKED_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 ID, hsScalar xPos, hsScalar yPos, hsScalar distance, int what, int reportType)
{
plPipeline* pipe = selfkey.GetPipeline();
if (pipe)
{
Int32 x=(Int32) ( xPos * pipe->Width() );
Int32 y=(Int32) ( 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 = TRACKED_NEW plLOSRequestMsg( selfkey.getKey(), startPos, endPos, plSimDefs::kLOSDBUIItems, plLOSRequestMsg::kTestClosest );
pMsg->SetCullDB(plSimDefs::kLOSDBUIBlockers);
break;
case kCameraBlockers:
pMsg = TRACKED_NEW plLOSRequestMsg( selfkey.getKey(), startPos, endPos, plSimDefs::kLOSDBCameraBlockers, plLOSRequestMsg::kTestClosest );
break;
case kCustom:
pMsg = TRACKED_NEW plLOSRequestMsg( selfkey.getKey(), startPos, endPos, plSimDefs::kLOSDBCustom, plLOSRequestMsg::kTestClosest );
break;
case kShootable:
pMsg = TRACKED_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, hsScalar xPos, hsScalar yPos, hsScalar radius, hsScalar range)
{
plPipeline* pipe = selfkey.GetPipeline();
if (pipe)
{
Int32 x=(Int32) ( xPos * pipe->Width() );
Int32 y=(Int32) ( 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 = TRACKED_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, hsScalar radius, hsScalar 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 = TRACKED_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 context )
{}
void OperationComplete( UInt32 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 nAgeInfoEntries;
ageInfoStream->GetStream()->ReadSwap( &nAgeInfoEntries );
UInt16 nPlayerCountEntries;
nPlayersStream->GetStream()->ReadSwap( &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 nPlayers;
ageInfo.Read( ageInfoStream->GetStream(), nil );
nPlayersStream->GetStream()->ReadSwap( &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());
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 wStr[MAX_PATH];
StrToUnicode(wStr, pfKIMsg::kChronicleKILevel, arrsize(wStr));
if (RelVaultNode * rvn = VaultFindChronicleEntryIncRef(wStr)) {
VaultChronicleNode chron(rvn);
result = _wtoi(chron.entryValue);
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();
(ret==nil) ? "empty" : ret;
char str[256];
sprintf(str, "saving camera named %s to chronicle\n",ret);
plVirtualCam1::Instance()->AddMsgToLog(str);
return ret;
}
plVirtualCam1::Instance()->AddMsgToLog("sending empty to camera chronicle\n");
return "empty";
}
void cyMisc::RebuildCameraStack(const char* name, const char* ageName)
{
plKey key=nil;
char str[256];
sprintf(str, "attempting to restore camera named %s from chronicle\n",name);
plVirtualCam1::Instance()->AddMsgToLog(str);
if (strcmp(name, "empty") == 0)
return;
if ( name || name[0] != 0)
{
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();
char errmsg[256];
sprintf(errmsg,"Sceneobject %s not found",name);
PyErr_SetString(PyExc_NameError, errmsg);
}
}
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();
char errmsg[256];
sprintf(errmsg,"Sceneobject %s has no camera modifier",name);
PyErr_SetString(PyExc_NameError, errmsg);
}
}
void cyMisc::PyClearCameraStack()
{
plVirtualCam1::Instance()->ClearStack();
}
void cyMisc::RecenterCamera()
{
plCameraMsg* pCam = TRACKED_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 = TRACKED_NEW plTransitionMsg( noSound ? plTransitionMsg::kFadeInNoSound : plTransitionMsg::kFadeIn, lenTime, holdFlag );
plgDispatch::MsgSend( msg );
}
void cyMisc::FadeOut(float lenTime, bool holdFlag, bool noSound)
{
plTransitionMsg *msg = TRACKED_NEW plTransitionMsg( noSound ? plTransitionMsg::kFadeOutNoSound : plTransitionMsg::kFadeOut, lenTime, holdFlag );
plgDispatch::MsgSend( msg );
}
void cyMisc::SetClickability(hsBool b)
{
plInputIfaceMgrMsg* msg = TRACKED_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 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 width, UInt16 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 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 = TRACKED_NEW plPseudoLinkEffectMsg;
msg->fAvatarKey = avatar.getKey();
msg->fLinkObjKey = object.getKey();
plgDispatch::MsgSend(msg);
}
void cyMisc::FakeLinkToObjectNamed(const char* name)
{
plKey key = nil;
if ( name || name[0] != 0)
{
key = plKeyFinder::Instance().StupidSearch(nil,nil,plSceneObject::Index(), name, false);
}
if (!key)
return;
plPseudoLinkEffectMsg* msg = TRACKED_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 = TRACKED_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 email[], const wchar 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
);
}