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.
2855 lines
81 KiB
2855 lines
81 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/>. |
|
|
|
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 "../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 |
|
); |
|
}
|
|
|