/*==LICENSE==* CyanWorlds.com Engine - MMOG client, server and tools Copyright (C) 2011 Cyan Worlds, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . You can contact Cyan Worlds, Inc. by email legal@cyan.com or by snail mail at: Cyan Worlds, Inc. 14617 N Newport Hwy Mead, WA 99021 *==LICENSE==*/ #include "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 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(); } time_t cyMisc::GetDniTime(void) { const plUnifiedTime utime = plNetClientMgr::GetInstance()->GetServerTime(); if ( utime.GetSecs() != 0) return ConvertGMTtoDni(utime.GetSecs()); else return 0; } time_t cyMisc::GetServerTime(void) { const plUnifiedTime utime = plNetClientMgr::GetInstance()->GetServerTime(); return utime.GetSecs(); } float cyMisc::GetAgeTimeOfDayPercent(void) { return plNetClientMgr::GetInstance()->GetCurrentAgeTimeOfDayPercent(); } #define kMST (UInt32)25200 #define kOneHour (UInt32)3600 #define kOneDay (UInt32)86400 time_t cyMisc::ConvertGMTtoDni(time_t gtime) { // convert to mountain time time_t dtime = gtime - kMST; plUnifiedTime utime = plUnifiedTime(); utime.SetSecs(dtime); // check for daylight savings time in New Mexico and adjust if ( utime.GetMonth() >= 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) int days_to_go = 7 - dstStart.GetDayOfWeek(); if (days_to_go == 7) days_to_go = 0; time_t dstStartSecs = dstStart.GetSecs() + days_to_go * kOneDay; plUnifiedTime dstEnd = plUnifiedTime(); dstEnd.SetGMTime(utime.GetYear(),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; time_t dstEndSecs = dstEnd.GetSecs() + days_to_go * kOneDay; if ( dtime > dstStartSecs && dtime < dstEndSecs ) // add hour for daylight savings time dtime += kOneHour; } return dtime; } ///////////////////////////////////////////////////////////////////////////// // // Function : ExcludeRegionSet // PARAMETERS : key - of the exclude region, ie. where to send the message // state - what state of to set at: // 0 = release // 1 = clear // // PURPOSE : Sets the state of an exclude region // void cyMisc::ExcludeRegionSet(pyKey& sender, pyKey& exKey, UInt16 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 cyMisc::GetPlayerList() { std::vector 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 cyMisc::GetPlayerListDistanceSorted() { std::vector 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 & 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 ; iGetPlayerID() ) ) msg->AddNetReceiver(tolist[i]->GetPlayerID()); } } UInt32 msgFlags = msg->GetFlags(); if (tolist.size() == 0 || (msg->GetNetReceivers() && msg->GetNetReceivers()->size() > 0)) msg->Send(); return msgFlags; } UInt32 cyMisc::SendRTChat(pyPlayer& from, const std::vector & tolist, const wchar_t* 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 for ( int 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 & tolist) { if (tolist.size() > 0) { plNetVoiceListMsg* pMsg = TRACKED_NEW plNetVoiceListMsg(plNetVoiceListMsg::kForcedListenerMode); for (int i=0 ; iGetClientList()->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 & 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(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(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(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(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; iGetStream(), 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 & 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 *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 ); }