/*==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 . 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 "HeadSpin.h" #include "plResponderLink.h" #include "plResponderComponentPriv.h" #include "resource.h" #include "max.h" #include "../MaxMain/plMaxNode.h" #include "hsResMgr.h" #include "plMiscComponents.h" // Needed for the dialog #include "../MaxMain/plMaxCFGFile.h" #include "../plFile/hsFiles.h" #include "../plAgeDescription/plAgeDescription.h" // Needed to create the message #include "../plMessage/plLinkToAgeMsg.h" #include "../pnNetCommon/pnNetCommon.h" #include "../pnKeyedObject/plFixedKey.h" #include "../pnSceneObject/plSceneObject.h" #include "../plNetCommon/plNetCommon.h" #include "../plNetCommon/plSpawnPointInfo.h" enum { kLinkAge_DEAD, kLinkSpawn_DEAD, kLinkType_DEAD, kLinkNexusLinkSpawn_DEAD, kLinkAddToPersonalLinks_DEAD, kLinkAddToNexusLinks_DEAD, kLinkName_DEAD, kLinkingRule, kLinkAgeFilename, kLinkAgeInstanceName, kLinkAgeSpawnPointTitle, kLinkAgeSpawnPointName, kLinkAgeLinkInAnimName, kLinkParentAgeFilename, kLinkAgeInstanceGuid, }; #define kDefaultLinkInAnimName "LinkOut" class plResponderLinkProc; extern plResponderLinkProc gResponderLinkProc; ParamBlockDesc2 gResponderLinkBlock ( kResponderLnkBlk, _T("linkCmd"), 0, NULL, P_AUTO_UI, IDD_COMP_RESPOND_LINK, IDS_COMP_CMD_PARAMS, 0, 0, &gResponderLinkProc, kLinkingRule, _T("linkingRule"), TYPE_INT, 0, 0, p_default, plNetCommon::LinkingRules::kBasicLink, end, kLinkAgeFilename, _T("ageFilename"), TYPE_STRING, 0, 0, end, kLinkAgeInstanceName, _T("ageInstanceName"), TYPE_STRING, 0, 0, p_ui, TYPE_EDITBOX, IDC_LINKAGEINSTANCENAME, end, kLinkAgeSpawnPointName, _T("ageSpawnPoint"), TYPE_STRING, 0, 0, p_ui, TYPE_EDITBOX, IDC_LINKSPAWNPOINT, p_default, kDefaultSpawnPtName, end, kLinkAgeSpawnPointTitle, _T("ageSpawnPointTitle"), TYPE_STRING, 0, 0, p_ui, TYPE_EDITBOX, IDC_LINKSPAWNPOINTTITLE, p_default, kDefaultSpawnPtTitle, end, kLinkAgeLinkInAnimName, _T("ageLinkInAnimName"), TYPE_STRING, 0, 0, p_ui, TYPE_EDITBOX, IDC_LINKAGELINKINANIMNAME, p_default, kDefaultLinkInAnimName, end, kLinkParentAgeFilename, _T("parentageFilename"), TYPE_STRING, 0, 0, end, kLinkAgeInstanceGuid, _T("ageInstanceGUID"), TYPE_STRING, 0, 0, p_ui, TYPE_EDITBOX, IDC_LINKAGEINSTANCEGUID, end, end ); plResponderCmdLink& plResponderCmdLink::Instance() { static plResponderCmdLink theInstance; return theInstance; } ParamBlockDesc2 *plResponderCmdLink::GetDesc() { return &gResponderLinkBlock; } const char *plResponderCmdLink::GetInstanceName(IParamBlock2 *pb) { static char name[256]; const char *ageName = pb->GetStr(kLinkAgeFilename); sprintf(name, "Link (%s)", (ageName && *ageName != '\0') ? ageName : "none"); return name; } void plResponderCmdLink::SetupProperties(plMaxNode* node, plErrorMsg* pErrMsg, IParamBlock2* pb) { char * spawnPtName = pb->GetStr( kLinkAgeSpawnPointName ); if ( !spawnPtName ) { // set defaults pb->SetValue( kLinkAgeSpawnPointName, 0, kDefaultSpawnPtName ); pb->SetValue( kLinkAgeSpawnPointTitle, 0, kDefaultSpawnPtTitle ); } else { char * spawnPtTitle = pb->GetStr( kLinkAgeSpawnPointTitle ); if ( !spawnPtTitle ) { // set default title, or make same as name. if ( strcmp( spawnPtName, kDefaultSpawnPtName )==0 ) pb->SetValue( kLinkAgeSpawnPointTitle, 0, kDefaultSpawnPtTitle ); else pb->SetValue( kLinkAgeSpawnPointTitle, 0, spawnPtName ); } } } plMessage *plResponderCmdLink::CreateMsg(plMaxNode* node, plErrorMsg *pErrMsg, IParamBlock2 *pb) { int linkingRule = pb->GetInt( kLinkingRule ); const char *ageFilename = pb->GetStr(kLinkAgeFilename); const char *ageInstanceName = pb->GetStr(kLinkAgeInstanceName); const char *ageSpawnPtName = pb->GetStr(kLinkAgeSpawnPointName); const char *ageSpawnPtTitle = pb->GetStr(kLinkAgeSpawnPointTitle); const char *ageLinkInAnimName = pb->GetStr(kLinkAgeLinkInAnimName); const char *parentageFilename = pb->GetStr(kLinkParentAgeFilename); const char *ageInstanceGuid = pb->GetStr(kLinkAgeInstanceGuid); if ( !ageFilename ) throw "Must specify Age Filename"; if ( !ageInstanceName ) ageInstanceName=ageFilename; if ( !ageSpawnPtName ) { ageSpawnPtName = kDefaultSpawnPtName; if ( !ageSpawnPtTitle ) ageSpawnPtTitle = kDefaultSpawnPtTitle; } if ( !ageSpawnPtTitle ) ageSpawnPtTitle = ageSpawnPtName; if ( !ageLinkInAnimName ) ageLinkInAnimName = kDefaultLinkInAnimName; plLinkToAgeMsg *msg = TRACKED_NEW plLinkToAgeMsg; msg->GetAgeLink()->SetLinkingRules( linkingRule ); msg->GetAgeLink()->SetSpawnPoint( plSpawnPointInfo( ageSpawnPtTitle, ageSpawnPtName ) ); msg->GetAgeLink()->GetAgeInfo()->SetAgeFilename( ageFilename ); msg->GetAgeLink()->GetAgeInfo()->SetAgeInstanceName( ageInstanceName ); if (ageInstanceGuid && strlen(ageInstanceGuid) > 0) msg->GetAgeLink()->GetAgeInfo()->SetAgeInstanceGuid( &plUUID(ageInstanceGuid) ); msg->SetLinkInAnimName( ageLinkInAnimName ); if (parentageFilename) { if (strcmp(parentageFilename, "") != 0) // is our special string to denote no parent age msg->GetAgeLink()->SetParentAgeFilename( parentageFilename ); } return msg; } class plResponderLinkProc : public ParamMap2UserDlgProc { protected: void ILoadLinkingRulesCombo(HWND hWnd, IParamBlock2* pb); void ILoadAgeFilenamesCombo(HWND hWnd, IParamBlock2 *pb); void ILoadParentAgeFilenamesCombo(HWND hWnd, IParamBlock2 *pb); public: BOOL DlgProc(TimeValue t, IParamMap2 *pm, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_INITDIALOG: ILoadLinkingRulesCombo(hWnd, pm->GetParamBlock()); ILoadAgeFilenamesCombo(hWnd, pm->GetParamBlock()); ILoadParentAgeFilenamesCombo(hWnd, pm->GetParamBlock()); return TRUE; case WM_COMMAND: if (HIWORD(wParam) == CBN_SELCHANGE) { int sel = ComboBox_GetCurSel((HWND)lParam); if (sel != CB_ERR) { if (LOWORD(wParam) == IDC_LINKINGRULE) { int data = ComboBox_GetItemData((HWND)lParam, sel); pm->GetParamBlock()->SetValue(kLinkingRule, 0, data); return TRUE; } else if (LOWORD(wParam) == IDC_LINKAGEFILENAME) { char buf[256]; SendMessage((HWND)lParam, CB_GETLBTEXT, sel, (LPARAM)buf); pm->GetParamBlock()->SetValue(kLinkAgeFilename, 0, buf); return TRUE; } else if (LOWORD(wParam) == IDC_PARENTAGEFILENAME) { char buf[256]; SendMessage((HWND)lParam, CB_GETLBTEXT, sel, (LPARAM)buf); pm->GetParamBlock()->SetValue(kLinkParentAgeFilename, 0, buf); return TRUE; } } } break; } return FALSE; } void DeleteThis() {} }; static plResponderLinkProc gResponderLinkProc; static int ComboBox_AddStringData(HWND hCombo, const char* str, int data) { int idx = ComboBox_AddString(hCombo, str); ComboBox_SetItemData(hCombo, idx, data); return idx; } void plResponderLinkProc::ILoadLinkingRulesCombo(HWND hWnd, IParamBlock2* pb) { HWND hType = GetDlgItem(hWnd, IDC_LINKINGRULE); ComboBox_ResetContent(hType); int type = pb->GetInt(kLinkingRule); using namespace plNetCommon::LinkingRules; ComboBox_AddStringData(hType, LinkingRuleStr(kBasicLink), kBasicLink); ComboBox_AddStringData(hType, LinkingRuleStr(kOriginalBook), kOriginalBook); ComboBox_AddStringData(hType, LinkingRuleStr(kSubAgeBook), kSubAgeBook); ComboBox_AddStringData(hType, LinkingRuleStr(kOwnedBook), kOwnedBook); ComboBox_AddStringData(hType, LinkingRuleStr(kVisitBook), kVisitBook); ComboBox_AddStringData(hType, LinkingRuleStr(kChildAgeBook), kChildAgeBook); int count = ComboBox_GetCount(hType); for (int i = 0; i < count; i++) { if (type == ComboBox_GetItemData(hType, i)) { ComboBox_SetCurSel(hType, i); break; } } } void plResponderLinkProc::ILoadAgeFilenamesCombo(HWND hWnd, IParamBlock2 *pb) { HWND hAge = GetDlgItem(hWnd, IDC_LINKAGEFILENAME); // Reset the combo and add the default option SendMessage(hAge, CB_RESETCONTENT, 0, 0); // Get the path to the description folder char agePath[MAX_PATH]; const char *plasmaPath = plMaxConfig::GetClientPath(); if (!plasmaPath) return; strcpy(agePath, plasmaPath); strcat(agePath, plAgeDescription::kAgeDescPath); const char *savedName = pb->GetStr(kLinkAgeFilename); if (!savedName) savedName = ""; // Iterate through the age descriptions hsFolderIterator ageFolder(agePath); while (ageFolder.NextFileSuffix(".age")) { char ageFile[MAX_PATH]; ageFolder.GetPathAndName(ageFile); char name[_MAX_FNAME]; _splitpath(ageFile, nil, nil, name, nil); int idx = SendMessage(hAge, CB_ADDSTRING, 0, (LPARAM)name); if (hsStrEQ(name, savedName)) SendMessage(hAge, CB_SETCURSEL, idx, 0); } } void plResponderLinkProc::ILoadParentAgeFilenamesCombo(HWND hWnd, IParamBlock2 *pb) { HWND hAge = GetDlgItem(hWnd, IDC_PARENTAGEFILENAME); // Reset the combo and add the default option SendMessage(hAge, CB_RESETCONTENT, 0, 0); SendMessage(hAge, CB_ADDSTRING, 0, (LPARAM)""); // Get the path to the description folder char agePath[MAX_PATH]; const char *plasmaPath = plMaxConfig::GetClientPath(); if (!plasmaPath) return; strcpy(agePath, plasmaPath); strcat(agePath, plAgeDescription::kAgeDescPath); const char *savedName = pb->GetStr(kLinkParentAgeFilename); if (!savedName) savedName = ""; // Iterate through the age descriptions hsFolderIterator ageFolder(agePath); while (ageFolder.NextFileSuffix(".age")) { char ageFile[MAX_PATH]; ageFolder.GetPathAndName(ageFile); char name[_MAX_FNAME]; _splitpath(ageFile, nil, nil, name, nil); int idx = SendMessage(hAge, CB_ADDSTRING, 0, (LPARAM)name); if (hsStrEQ(name, savedName)) SendMessage(hAge, CB_SETCURSEL, idx, 0); } } /////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////// #include "plComponentBase.h" // Needed for message creation #include "../plModifier/plResponderModifier.h" enum { kEnable, kEnableNode, kEnableResponder, }; class plResponderEnableProc; extern plResponderEnableProc gResponderEnableProc; ParamBlockDesc2 gResponderEnableBlock ( kResponderEnableMsgBlk, _T("enableCmd"), 0, NULL, P_AUTO_UI, IDD_COMP_RESPOND_ENABLE, IDS_COMP_CMD_PARAMS, 0, 0, &gResponderEnableProc, kEnable, _T("enable"), TYPE_BOOL, 0, 0, p_ui, TYPE_SINGLECHEKBOX, IDC_ENABLE_CHECK, p_default, TRUE, end, kEnableNode, _T("node"), TYPE_REFTARG, 0, 0, end, kEnableResponder, _T("responder"), TYPE_REFTARG, P_NO_REF, 0, end, end ); plResponderCmdEnable& plResponderCmdEnable::Instance() { static plResponderCmdEnable theInstance; return theInstance; } ParamBlockDesc2 *plResponderCmdEnable::GetDesc() { return &gResponderEnableBlock; } #include "plResponderGetComp.h" const char *plResponderCmdEnable::GetInstanceName(IParamBlock2 *pb) { static char name[256]; plComponentBase *comp = plResponderGetComp::Instance().GetSavedComp(pb, kEnableNode, kEnableResponder, true); sprintf(name, "Responder Enable (%s)", comp ? comp->GetINode()->GetName() : "none"); return name; } plMessage *plResponderCmdEnable::CreateMsg(plMaxNode* node, plErrorMsg *pErrMsg, IParamBlock2 *pb) { plComponentBase *comp = plResponderGetComp::Instance().GetSavedComp(pb, kEnableNode, kEnableResponder, true); if (!comp) throw "No responder component specified"; BOOL enable = pb->GetInt(kEnable); plResponderEnableMsg *msg = TRACKED_NEW plResponderEnableMsg; msg->fEnable = (enable != false); plMaxNodeBase *respondNode = (plMaxNodeBase*)pb->GetReferenceTarget(kEnableNode); plKey responderKey = Responder::GetKey(comp, respondNode); msg->AddReceiver(responderKey); return msg; } class plResponderEnableProc : public ParamMap2UserDlgProc { protected: void IUpdateButton(HWND hWnd, IParamBlock2 *pb) { HWND hComp = GetDlgItem(hWnd, IDC_RESPONDER_BUTTON); plComponentBase *comp = plResponderGetComp::Instance().GetSavedComp(pb, kEnableNode, kEnableResponder); if (comp) SetWindowText(hComp, comp->GetINode()->GetName()); else SetWindowText(hComp, "(none)"); } public: BOOL DlgProc(TimeValue t, IParamMap2 *pm, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_INITDIALOG: { IParamBlock2 *pb = pm->GetParamBlock(); IUpdateButton(hWnd, pb); } return TRUE; case WM_COMMAND: if (HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDC_RESPONDER_BUTTON) { IParamBlock2 *pb = pm->GetParamBlock(); // If the responder component is hosed, remove it so the plResponderGetComp won't get bogus info if (!plResponderGetComp::Instance().GetSavedComp(pb, kEnableNode, kEnableResponder)) { ReferenceTarget *empty = nil; pb->SetValue(kEnableResponder, 0, empty); } plResponderGetComp::ClassIDs cids; cids.push_back(RESPONDER_CID); plResponderGetComp::Instance().GetComp(pb, kEnableNode, kEnableResponder, &cids); IUpdateButton(hWnd, pb); } break; } return FALSE; } void DeleteThis() {} }; static plResponderEnableProc gResponderEnableProc; /////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////// #include "../pnMessage/plEnableMsg.h" enum { kEnablePhys, kEnablePhysNode, }; ParamBlockDesc2 gPhysicalEnableBlock ( kResponderPhysEnableBlk, _T("physEnableCmd"), 0, NULL, P_AUTO_UI, IDD_COMP_RESPOND_ENABLE_PHYS, IDS_COMP_CMD_PARAMS, 0, 0, NULL, kEnablePhys, _T("enable"), TYPE_BOOL, 0, 0, p_ui, TYPE_SINGLECHEKBOX, IDC_ENABLE_CHECK, p_default, TRUE, end, kEnablePhysNode, _T("node"), TYPE_INODE, 0, 0, p_ui, TYPE_PICKNODEBUTTON, IDC_NODE_BUTTON, end, end ); plResponderCmdPhysEnable& plResponderCmdPhysEnable::Instance() { static plResponderCmdPhysEnable theInstance; return theInstance; } ParamBlockDesc2 *plResponderCmdPhysEnable::GetDesc() { return &gPhysicalEnableBlock; } const char *plResponderCmdPhysEnable::GetInstanceName(IParamBlock2 *pb) { static char name[256]; INode *node = pb->GetINode(kEnablePhysNode); sprintf(name, "Phys Enable (%s)", node ? node->GetName() : "none"); return name; } #include "../plMessage/plSimStateMsg.h" plMessage *plResponderCmdPhysEnable::CreateMsg(plMaxNode* node, plErrorMsg *pErrMsg, IParamBlock2 *pb) { plMaxNode* physNode = (plMaxNode*)pb->GetINode(kEnablePhysNode); if (!physNode) throw "No physical selected"; BOOL enable = pb->GetInt(kEnable); plEnableMsg* enableMsg = TRACKED_NEW plEnableMsg; enableMsg->SetCmd(plEnableMsg::kPhysical); enableMsg->SetCmd(enable ? plEnableMsg::kEnable : plEnableMsg::kDisable); enableMsg->AddReceiver(physNode->GetKey()); return enableMsg; } /////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////// enum { kOneShotComp, kOneShotNode, }; class plResponderOneShotProc; extern plResponderOneShotProc gResponderOneShotProc; ParamBlockDesc2 gResponderOneShotBlock ( kResponderOneShotMsgBlk, _T("oneShotCmd"), 0, NULL, P_AUTO_UI, IDD_COMP_RESPOND_ONESHOT, IDS_COMP_CMD_PARAMS, 0, 0, &gResponderOneShotProc, kOneShotComp, _T("oneShotComp"), TYPE_REFTARG, 0, 0, end, kOneShotNode, _T("oneShotNode"), TYPE_REFTARG, 0, 0, end, end ); plResponderCmdOneShot& plResponderCmdOneShot::Instance() { static plResponderCmdOneShot theInstance; return theInstance; } ParamBlockDesc2 *plResponderCmdOneShot::GetDesc() { return &gResponderOneShotBlock; } const char *plResponderCmdOneShot::GetInstanceName(IParamBlock2 *pb) { static char name[256]; plMaxNode *node = (plMaxNode*)pb->GetReferenceTarget(kOneShotComp); sprintf(name, "One Shot (%s)", node ? node->GetName() : "none"); return name; } #include "../plMessage/plOneShotMsg.h" #include "plOneShotComponent.h" plMessage *plResponderCmdOneShot::CreateMsg(plMaxNode* node, plErrorMsg *pErrMsg, IParamBlock2 *pb) { plResponderCompNode compNode; plResponderCompNode::ClassIDs cids; cids.push_back(ONESHOTCLASS_ID); compNode.Init(pb, kOneShotComp, kOneShotNode, IDC_RESPONDER_COMP, IDC_RESPONDER_NODE, &cids); plComponentBase *comp; plMaxNodeBase *targNode; if (compNode.GetCompAndNode(comp, targNode)) { plKey oneShotKey = OneShotComp::GetOneShotKey(comp, targNode); if (!oneShotKey) throw "One-shot component didn't convert"; plOneShotMsg *msg = TRACKED_NEW plOneShotMsg; msg->AddReceiver(oneShotKey); return msg; } else throw "No one-shot component specified"; } #include "../plMessage/plOneShotCallbacks.h" void plResponderCmdOneShot::CreateWait(plMaxNode* node, plErrorMsg* pErrMsg, IParamBlock2 *pb, ResponderWaitInfo& waitInfo) { plOneShotMsg *oneShotMsg = plOneShotMsg::ConvertNoRef(waitInfo.msg); hsAssert(oneShotMsg, "Bad One-Shot message"); if (oneShotMsg) oneShotMsg->fCallbacks->AddCallback(waitInfo.point, waitInfo.receiver, waitInfo.callbackUser); } class plResponderOneShotProc : public ParamMap2UserDlgProc { protected: plResponderCompNode fCompNode; public: BOOL DlgProc(TimeValue t, IParamMap2 *pm, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_INITDIALOG: { IParamBlock2 *pb = pm->GetParamBlock(); plResponderCompNode::ClassIDs cids; cids.push_back(ONESHOTCLASS_ID); fCompNode.Init(pb, kOneShotComp, kOneShotNode, IDC_RESPONDER_COMP, IDC_RESPONDER_NODE, &cids); fCompNode.InitDlg(hWnd); } return TRUE; case WM_COMMAND: if (HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDC_RESPONDER_COMP) { fCompNode.CompButtonPress(hWnd); return TRUE; } else if (HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDC_RESPONDER_NODE) { fCompNode.NodeButtonPress(hWnd); return TRUE; } break; } return FALSE; } void DeleteThis() {} }; static plResponderOneShotProc gResponderOneShotProc; /////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////// ParamBlockDesc2 gResponderNotifyBlock ( kResponderNotifyMsgBlk, _T("notifyCmd"), 0, NULL, 0, end ); plResponderCmdNotify& plResponderCmdNotify::Instance() { static plResponderCmdNotify theInstance; return theInstance; } ParamBlockDesc2 *plResponderCmdNotify::GetDesc() { return &gResponderNotifyBlock; } #include "../pnMessage/plNotifyMsg.h" plMessage *plResponderCmdNotify::CreateMsg(plMaxNode* node, plErrorMsg *pErrMsg, IParamBlock2 *pb) { plNotifyMsg *msg = TRACKED_NEW plNotifyMsg; msg->SetBCastFlag(plMessage::kNetPropagate, 0); msg->SetState(1.0); // set to positive state msg->AddCallbackEvent(1); // create an event record with callback return msg; } /////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////// #include "plCameraComponents.h" class plResponderActivatorEnableProc; extern plResponderActivatorEnableProc gResponderActivatorEnableProc; enum { kActivatorComp, kActivatorEnable }; ParamBlockDesc2 gResponderActivatorEnableBlock ( kResponderActivatorEnableBlk, _T("detectorEnable"), 0, NULL, P_AUTO_UI, IDD_COMP_RESPOND_ENABLE, IDS_COMP_CMD_PARAMS, 0, 0, &gResponderActivatorEnableProc, kActivatorComp, _T("activatorComp"), TYPE_INODE, 0, 0, end, kActivatorEnable, _T("enable"), TYPE_BOOL, 0, 0, p_ui, TYPE_SINGLECHEKBOX, IDC_ENABLE_CHECK, p_default, TRUE, end, end ); plResponderCmdDetectorEnable& plResponderCmdDetectorEnable::Instance() { static plResponderCmdDetectorEnable theInstance; return theInstance; } ParamBlockDesc2 *plResponderCmdDetectorEnable::GetDesc() { return &gResponderActivatorEnableBlock; } const char *plResponderCmdDetectorEnable::GetInstanceName(IParamBlock2 *pb) { static char name[256]; plMaxNode *node = (plMaxNode*)pb->GetINode(kActivatorComp); sprintf(name, "Enable Detector (%s)", node ? node->GetName() : "none"); return name; } #include "../pnMessage/plEnableMsg.h" #include "plActivatorBaseComponent.h" #include "plVolumeGadgetComponent.h" #include "plNavigableComponents.h" plMessage *plResponderCmdDetectorEnable::CreateMsg(plMaxNode* node, plErrorMsg *pErrMsg, IParamBlock2 *pb) { plMaxNode *detectNode = (plMaxNode*)pb->GetINode(kActivatorComp); if (!detectNode) throw "No detector component specified"; plComponentBase *comp = detectNode->ConvertToComponent(); if (!comp || (comp->CanConvertToType(ACTIVATOR_BASE_CID) == 0 && comp->ClassID() != NAV_LADDER_CID && comp->ClassID() != CAM_REGION_CID)) throw "Not a detector component"; BOOL enable = pb->GetInt(kActivatorEnable); // Just stuffing this in here because I'm lazy if (comp->ClassID() == CAM_REGION_CID) { plEnableMsg* enableMsg = TRACKED_NEW plEnableMsg; enableMsg->SetCmd(plEnableMsg::kPhysical); enableMsg->SetCmd(enable ? plEnableMsg::kEnable : plEnableMsg::kDisable); for (int i = 0; i < comp->NumTargets(); i++) enableMsg->AddReceiver(comp->GetTarget(i)->GetKey()); return enableMsg; } plEnableMsg *msg = TRACKED_NEW plEnableMsg; msg->SetCmd(enable ? plEnableMsg::kEnable : plEnableMsg::kDisable); hsTArray keys; if (comp->CanConvertToType(ACTIVATOR_BASE_CID)) { // Add each activator mod to the receiver list plActivatorBaseComponent *activatorComp = (plActivatorBaseComponent*)comp; const plActivatorBaseComponent::LogicKeys& logicKeys = activatorComp->GetLogicKeys(); plActivatorBaseComponent::LogicKeys::const_iterator it; for (it = logicKeys.begin(); it != logicKeys.end(); it++) { plKey key = it->second; keys.Append(key); } // check to see if this is a region sensor and if so if it has exit and / or enter activators if (activatorComp->HasLogicOut()) { plVolumeGadgetComponent *volComp = (plVolumeGadgetComponent*)comp; const plActivatorBaseComponent::LogicKeys& logicKeys = volComp->GetLogicOutKeys(); plActivatorBaseComponent::LogicKeys::const_iterator it; for (it = logicKeys.begin(); it != logicKeys.end(); it++) { plKey key = it->second; keys.Append(key); } } } else if (comp->ClassID() == NAV_LADDER_CID) { plAvLadderComponent *ladderComp = (plAvLadderComponent*)comp; keys = ladderComp->GetLadderModKeys(); } msg->AddReceivers(keys); return msg; } #include "plPickNode.h" class plResponderActivatorEnableProc : public ParamMap2UserDlgProc { protected: void IUpdateButton(IParamBlock2 *pb, HWND hWnd) { INode *node = pb->GetINode(kActivatorComp); if (node) SetDlgItemText(hWnd, IDC_RESPONDER_BUTTON, node->GetName()); else SetDlgItemText(hWnd, IDC_RESPONDER_BUTTON, "(none)"); } public: BOOL DlgProc(TimeValue t, IParamMap2 *pm, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_INITDIALOG: IUpdateButton(pm->GetParamBlock(), hWnd); return TRUE; case WM_COMMAND: if (HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDC_RESPONDER_BUTTON) { if (plPick::DetectorEnable(pm->GetParamBlock(), kActivatorComp, true)) IUpdateButton(pm->GetParamBlock(), hWnd); return TRUE; } break; } return FALSE; } void DeleteThis() {} }; static plResponderActivatorEnableProc gResponderActivatorEnableProc; /////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////// class plResponderXRegionProc; extern plResponderXRegionProc gResponderXRegionProc; enum { kXRegionComp, kXRegionType, kXRegionNode }; ParamBlockDesc2 gResponderXRegionBlock ( kResponderXRegionBlk, _T("xRegion"), 0, NULL, P_AUTO_UI, IDD_COMP_RESPOND_ONESHOT, IDS_COMP_CMD_PARAMS, 0, 0, &gResponderXRegionProc, kXRegionComp, _T("xRegionComp"), TYPE_INODE, 0, 0, end, kXRegionNode, _T("xRegionNode"), TYPE_INODE, 0, 0, end, kXRegionType, _T("type"), TYPE_INT, 0, 0, end, end ); // Old types kept for backwards compatibility enum { kRespondXRegionClear=25, kRespondXRegionRelease, }; plResponderCmdXRegion& plResponderCmdXRegion::Instance() { static plResponderCmdXRegion theInstance; return theInstance; } ParamBlockDesc2 *plResponderCmdXRegion::GetDesc() { return &gResponderXRegionBlock; } IParamBlock2 *plResponderCmdXRegion::CreatePB(int idx) { IParamBlock2 *pb = CreateParameterBlock2(&gResponderXRegionBlock, nil); int type = kRespondXRegionClear; if (idx == 1) type = kRespondXRegionRelease; pb->SetValue(kXRegionType, 0, type); return pb; } int plResponderCmdXRegion::NumTypes() { return 2; } const char *plResponderCmdXRegion::GetCategory(int idx) { return "Exclude Region"; } const char *plResponderCmdXRegion::GetName(int idx) { if (idx == 0) return "Clear"; else return "Release"; } const char *plResponderCmdXRegion::GetInstanceName(IParamBlock2 *pb) { static char name[256]; int type = pb->GetInt(kXRegionType); INode *node = pb->GetINode(kXRegionComp); if (type == kRespondXRegionClear) sprintf(name, "XRegion Clear (%s)", node ? node->GetName() : "none"); else sprintf(name, "XRegion Release (%s)", node ? node->GetName() : "none"); return name; } #include "../plMessage/plExcludeRegionMsg.h" #include "plExcludeRegionComponent.h" plMessage *plResponderCmdXRegion::CreateMsg(plMaxNode* node, plErrorMsg *pErrMsg, IParamBlock2 *pb) { plResponderCompNode compNode; plResponderCompNode::ClassIDs cids; cids.push_back(XREGION_CID); compNode.Init(pb, kXRegionComp, kXRegionNode, IDC_RESPONDER_COMP, IDC_RESPONDER_NODE, &cids); plComponentBase *comp; plMaxNodeBase *targNode; if (compNode.GetCompAndNode(comp, targNode)) { plExcludeRegionComponent *xComp = (plExcludeRegionComponent*)comp; plExcludeRegionMsg *msg = TRACKED_NEW plExcludeRegionMsg; int type = pb->GetInt(kXRegionType); switch (type) { case kRespondXRegionClear: msg->SetCmd(plExcludeRegionMsg::kClear); break; case kRespondXRegionRelease: msg->SetCmd(plExcludeRegionMsg::kRelease); break; } msg->AddReceiver(xComp->GetKey((plMaxNode*)targNode)); return msg; } else throw "No exclude region component specified"; } class plResponderXRegionProc : public ParamMap2UserDlgProc { protected: plResponderCompNode fCompNode; public: BOOL DlgProc(TimeValue t, IParamMap2 *pm, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_INITDIALOG: { IParamBlock2 *pb = pm->GetParamBlock(); plResponderCompNode::ClassIDs cids; cids.push_back(XREGION_CID); fCompNode.Init(pb, kXRegionComp, kXRegionNode, IDC_RESPONDER_COMP, IDC_RESPONDER_NODE, &cids); fCompNode.InitDlg(hWnd); } return TRUE; case WM_COMMAND: if (HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDC_RESPONDER_COMP) { fCompNode.CompButtonPress(hWnd); return TRUE; } else if (HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDC_RESPONDER_NODE) { fCompNode.NodeButtonPress(hWnd); return TRUE; } break; } return FALSE; } void DeleteThis() {} }; static plResponderXRegionProc gResponderXRegionProc; /////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////// class plResponderCameraTransitionProc; extern plResponderCameraTransitionProc gResponderCameraTransitionProc; enum { kCameraObj, kPopCamera, }; ParamBlockDesc2 gResponderCameraTransitionBlock ( kResponderCameraTransitionBlk, _T("camera"), 0, NULL, P_AUTO_UI, IDD_COMP_RESPOND_CAMERA, IDS_COMP_CMD_PARAMS, 0, 0, NULL, kCameraObj, _T("CameraObj"), TYPE_INODE, 0, 0, p_ui, TYPE_PICKNODEBUTTON, IDC_COMP_CAMERARGN_PICKSTATE_BASE, p_sclassID, CAMERA_CLASS_ID, p_prompt, IDS_COMP_PHYS_CHOSEN_BASE, end, kPopCamera, _T("enable"), TYPE_BOOL, 0, 0, p_ui, TYPE_SINGLECHEKBOX, IDC_CHECK1, p_default, FALSE, end, end ); plResponderCmdCamTransition& plResponderCmdCamTransition::Instance() { static plResponderCmdCamTransition theInstance; return theInstance; } ParamBlockDesc2 *plResponderCmdCamTransition::GetDesc() { return &gResponderCameraTransitionBlock; } const char *plResponderCmdCamTransition::GetInstanceName(IParamBlock2 *pb) { static char name[256]; INode *node = pb->GetINode(kCameraObj); sprintf(name, "Cam Trans (%s)", node ? node->GetName() : "none"); return name; } #include "../pnMessage/plCameraMsg.h" #include "plCameraComponents.h" plMessage *plResponderCmdCamTransition::CreateMsg(plMaxNode* node, plErrorMsg *pErrMsg, IParamBlock2 *pb) { plMaxNode *pCamNode = (plMaxNode*)pb->GetINode(kCameraObj); if (!pCamNode) throw "No Camera Specified"; hsBool fail = true; int count = pCamNode->NumAttachedComponents(); for (UInt32 x = 0; x < count; x++) { plComponentBase *comp = ((plMaxNode*)pCamNode)->GetAttachedComponent(x); if (comp->ClassID() == AUTOCAM_CID || comp->ClassID() == FPCAM_CID || comp->ClassID() == FIXEDCAM_CID || comp->ClassID() == CIRCLE_CAM_CID || comp->ClassID() == RAIL_CAM_CID || comp->ClassID() == FOLLOWCAM_CID ) { fail = false; break; } } if (fail) throw "Invalid Camera Specified"; plCameraMsg* pMsg = TRACKED_NEW plCameraMsg; pMsg->SetBCastFlag(plMessage::kBCastByType); if(pCamNode->CanConvert()) { if (!pb->GetInt(kPopCamera)) pMsg->SetCmd(plCameraMsg::kResponderTrigger); pMsg->SetCmd(plCameraMsg::kRegionPushCamera); pMsg->SetNewCam(((plMaxNode*)pCamNode)->GetSceneObject()->GetKey()); int count = ((plMaxNode*)pCamNode)->NumAttachedComponents(); for (UInt32 x = 0; x < count; x++) { plComponentBase *comp = ((plMaxNode*)pCamNode)->GetAttachedComponent(x); if (comp->ClassID() == DEFAULTCAM_CID) { pMsg->SetCmd(plCameraMsg::kSetAsPrimary); break; } } } return pMsg; } /////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////// class plResponderCameraForceProc; extern plResponderCameraForceProc gResponderCameraForceProc; enum { kCamForce, }; ParamBlockDesc2 gResponderCameraForceBlock ( kResponderCameraForceBlk, _T("cameraForce"), 0, NULL, P_AUTO_UI, IDD_COMP_RESPOND_CAM_FORCE, IDS_COMP_CMD_PARAMS, 0, 0, NULL, kCamForce, _T("force"), TYPE_INT, 0, 0, p_ui, TYPE_RADIO, 2, IDC_RADIO_THIRD, IDC_RADIO_FIRST, p_vals, plResponderCmdCamForce::kForce3rd, plResponderCmdCamForce::kResume1st, p_default, plResponderCmdCamForce::kForce3rd, end, end ); plResponderCmdCamForce& plResponderCmdCamForce::Instance() { static plResponderCmdCamForce theInstance; return theInstance; } ParamBlockDesc2 *plResponderCmdCamForce::GetDesc() { return &gResponderCameraForceBlock; } const char *plResponderCmdCamForce::GetInstanceName(IParamBlock2 *pb) { if (pb->GetInt(kCamForce) == kForce3rd) return "Cam Force 3rd"; else return "Cam Resume 1st"; } plMessage *plResponderCmdCamForce::CreateMsg(plMaxNode* node, plErrorMsg *pErrMsg, IParamBlock2 *pb) { plCameraMsg* msg = TRACKED_NEW plCameraMsg; msg->SetBCastFlag(plMessage::kBCastByType); msg->SetBCastFlag(plMessage::kNetPropagate, false); if (pb->GetInt(kCamForce) == kForce3rd) msg->SetCmd(plCameraMsg::kResponderSetThirdPerson); else msg->SetCmd(plCameraMsg::kResponderUndoThirdPerson); return msg; } /////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////// enum { kDelayTime }; ParamBlockDesc2 gResponderDelayBlock ( kResponderDelayBlk, _T("delay"), 0, NULL, P_AUTO_UI, IDD_COMP_RESPOND_DELAY, IDS_COMP_CMD_PARAMS, 0, 0, NULL, kDelayTime, _T("delay"), TYPE_FLOAT, 0, 0, p_default, 1.0f, p_range, 0.01f, 500.0f, p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, IDC_DELAY_EDIT, IDC_DELAY_SPIN, .1f, end, end ); plResponderCmdDelay& plResponderCmdDelay::Instance() { static plResponderCmdDelay theInstance; return theInstance; } ParamBlockDesc2 *plResponderCmdDelay::GetDesc() { return &gResponderDelayBlock; } const char *plResponderCmdDelay::GetInstanceName(IParamBlock2 *pb) { static char name[256]; sprintf(name, "Delay (%.1f sec)", pb->GetFloat(kDelayTime)); return name; } #include "../plMessage/plTimerCallbackMsg.h" plMessage *plResponderCmdDelay::CreateMsg(plMaxNode* node, plErrorMsg *pErrMsg, IParamBlock2 *pb) { float time = pb->GetFloat(kDelayTime); plTimerCallbackMsg *msg = TRACKED_NEW plTimerCallbackMsg; msg->fTime = time; msg->fID = UInt32(-1); return msg; } void plResponderCmdDelay::CreateWait(plMaxNode* node, plErrorMsg* pErrMsg, IParamBlock2 *pb, ResponderWaitInfo& waitInfo) { plTimerCallbackMsg *timerMsg = plTimerCallbackMsg::ConvertNoRef(waitInfo.msg); hsAssert(timerMsg, "Somebody is crazy"); if (timerMsg->fID != UInt32(-1)) { pErrMsg->Set(true, "Responder Delay", "A delay command in responder '%s' on node '%s' has\n" "more than one command waiting on it. That doesn't work.\n\n" "However, you don't actually need two commands to wait on\n" "the same command since the first command will automatically\n" "delay any commands further down the list", waitInfo.responderName, node->GetName()).Show(); pErrMsg->Set(false); } else { timerMsg->fID = waitInfo.callbackUser; timerMsg->AddReceiver(waitInfo.receiver); } } /////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////// enum { kVisibilityNode, kVisibilityType, kVisibilityChildren }; ParamBlockDesc2 gResponderVisibilityBlock ( kResponderVisibilityBlk, _T("Visibility"), 0, NULL, P_AUTO_UI, IDD_COMP_RESPOND_VISIBILITY, IDS_COMP_CMD_PARAMS, 0, 0, NULL, kVisibilityNode, _T("VisibilityNode"), TYPE_INODE, 0, 0, p_ui, TYPE_PICKNODEBUTTON, IDC_NODE_BUTTON, end, kVisibilityType, _T("type"), TYPE_INT, 0, 0, end, kVisibilityChildren, _T("children"), TYPE_BOOL, 0, 0, p_default, FALSE, p_ui, TYPE_SINGLECHEKBOX, IDC_CHECK_CHILDREN, end, end ); enum { kRespondVisibilityOn, kRespondVisibilityOff, }; plResponderCmdVisibility& plResponderCmdVisibility::Instance() { static plResponderCmdVisibility theInstance; return theInstance; } ParamBlockDesc2 *plResponderCmdVisibility::GetDesc() { return &gResponderVisibilityBlock; } IParamBlock2 *plResponderCmdVisibility::CreatePB(int idx) { IParamBlock2 *pb = CreateParameterBlock2(&gResponderVisibilityBlock, nil); int type = kRespondVisibilityOn; if (idx == 1) type = kRespondVisibilityOff; pb->SetValue(kVisibilityType, 0, type); return pb; } int plResponderCmdVisibility::NumTypes() { return 2; } const char *plResponderCmdVisibility::GetCategory(int idx) { return "Visibility"; } const char *plResponderCmdVisibility::GetName(int idx) { if (idx == 0) return "Visible"; else return "Invisible"; } const char *plResponderCmdVisibility::GetInstanceName(IParamBlock2 *pb) { static char name[256]; int type = pb->GetInt(kVisibilityType); INode *node = pb->GetINode(kVisibilityNode); if (type == kRespondVisibilityOn) sprintf(name, "Visible (%s)", node ? node->GetName() : "none"); else sprintf(name, "Invisible (%s)", node ? node->GetName() : "none"); return name; } #include "../pnMessage/plEnableMsg.h" static void AddChildKeysRecur(plMaxNode* node, plMessage* msg) { if (!node) return; plKey key = node->GetKey(); if (key) msg->AddReceiver(key); for (int i = 0; i < node->NumberOfChildren(); i++) AddChildKeysRecur((plMaxNode*)node->GetChildNode(i), msg); } plMessage *plResponderCmdVisibility::CreateMsg(plMaxNode* node, plErrorMsg *pErrMsg, IParamBlock2 *pb) { plMaxNode* visNode = (plMaxNode*)pb->GetINode(kVisibilityNode); if (visNode) { plEnableMsg* msg = TRACKED_NEW plEnableMsg; msg->SetCmd(plEnableMsg::kDrawable); int type = pb->GetInt(kVisibilityType); switch (type) { case kRespondVisibilityOn: msg->SetCmd(plEnableMsg::kEnable); break; case kRespondVisibilityOff: msg->SetCmd(plEnableMsg::kDisable); break; } if (pb->GetInt(kVisibilityChildren)) { // msg->SetBCastFlag(plMessage::kPropagateToChildren); AddChildKeysRecur(visNode, msg); } else msg->AddReceiver(visNode->GetKey()); return msg; } else throw "No node chosen"; } /////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////// enum { kSubWorldNode, kSubWorldType }; class plResponderSubWorldProc; extern plResponderSubWorldProc gResponderSubWorldProc; ParamBlockDesc2 gResponderSubWorldBlock ( kResponderSubWorldBlk, _T("SubWorld"), 0, NULL, P_AUTO_UI, IDD_COMP_RESPOND_SUBWORLD, IDS_COMP_CMD_PARAMS, 0, 0, &gResponderSubWorldProc, kSubWorldNode, _T("SubWorldNode"), TYPE_INODE, 0, 0, p_ui, TYPE_PICKNODEBUTTON, IDC_NODE_BUTTON, end, kSubWorldType, _T("type"), TYPE_INT, 0, 0, end, end ); enum { kRespondSubWorldEnter, kRespondSubWorldExit, }; plResponderCmdSubWorld& plResponderCmdSubWorld::Instance() { static plResponderCmdSubWorld theInstance; return theInstance; } ParamBlockDesc2 *plResponderCmdSubWorld::GetDesc() { return &gResponderSubWorldBlock; } IParamBlock2 *plResponderCmdSubWorld::CreatePB(int idx) { IParamBlock2 *pb = CreateParameterBlock2(&gResponderSubWorldBlock, nil); int type = kRespondSubWorldEnter; if (idx == 1) type = kRespondSubWorldExit; pb->SetValue(kSubWorldType, 0, type); return pb; } int plResponderCmdSubWorld::NumTypes() { return 2; } const char *plResponderCmdSubWorld::GetCategory(int idx) { return "Local Avatar"; } const char *plResponderCmdSubWorld::GetName(int idx) { if (idx == 0) return "Subworld Enter"; else return "Subworld Exit"; } const char *plResponderCmdSubWorld::GetInstanceName(IParamBlock2 *pb) { static char name[256]; int type = pb->GetInt(kSubWorldType); INode *node = pb->GetINode(kSubWorldNode); if (type == kRespondSubWorldEnter) sprintf(name, "Subworld Enter (%s)", node ? node->GetName() : "none"); else sprintf(name, "Subworld Exit"); //sprintf(name, "SubWorld Exit (%s)", node ? node->GetName() : "none"); return name; } plMessage *plResponderCmdSubWorld::CreateMsg(plMaxNode* node, plErrorMsg *pErrMsg, IParamBlock2 *pb) { plMaxNode* swNode = (plMaxNode*)pb->GetINode(kSubWorldNode); int type = pb->GetInt(kSubWorldType); plKey worldKey; plKey nilKey; plKey nilKey2; switch (type) { case kRespondSubWorldEnter: if (swNode) { worldKey = swNode->GetKey(); } else throw "No node chosen"; break; case kRespondSubWorldExit: // worldKey is already nil key so leave it that way break; } plSubWorldMsg * swMsg = TRACKED_NEW plSubWorldMsg(nilKey, nilKey2, worldKey); return swMsg; } class plResponderSubWorldProc : public ParamMap2UserDlgProc { public: BOOL DlgProc(TimeValue t, IParamMap2 *pm, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_INITDIALOG: { IParamBlock2 *pb = pm->GetParamBlock(); int type = pb->GetInt(kSubWorldType); HWND nButton = GetDlgItem(hWnd, IDC_NODE_BUTTON); //HWND sEnterText = GetDlgItem(hWnd, IDC_SUBWORLD_ENTER); HWND sExitText = GetDlgItem(hWnd, IDC_SUBWORLD_EXIT); BOOL isEnter = (type == kRespondSubWorldEnter) ? TRUE : FALSE; ShowWindow(nButton, (isEnter) ? SW_SHOW : SW_HIDE); //ShowWindow(sEnterText,(isEnter) ? SW_SHOW : SW_HIDE); ShowWindow(sExitText, (isEnter) ? SW_HIDE : SW_SHOW); } return TRUE; case WM_COMMAND: break; } return FALSE; } void DeleteThis() {} }; static plResponderSubWorldProc gResponderSubWorldProc; /////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////// #include "../pfMessage/plArmatureEffectMsg.h" #include "../plAvatar/plArmatureEffects.h" class plResponderFootSurfaceProc; extern plResponderFootSurfaceProc gResponderFootSurfaceProc; enum { kSurface, }; ParamBlockDesc2 gResponderFootSurfaceBlock ( kResponderFootSurfaceBlk, _T("FootSurface"), 0, NULL, P_AUTO_UI, IDD_COMP_RESPOND_FOOT_SURFACE, IDS_COMP_CMD_PARAMS, 0, 0, &gResponderFootSurfaceProc, kSurface, _T("Surface"), TYPE_INT, 0, 0, p_default, plArmatureEffectsMgr::kFootDirt, end, end ); plResponderCmdFootSurface& plResponderCmdFootSurface::Instance() { static plResponderCmdFootSurface theInstance; return theInstance; } ParamBlockDesc2 *plResponderCmdFootSurface::GetDesc() { return &gResponderFootSurfaceBlock; } const char *plResponderCmdFootSurface::GetInstanceName(IParamBlock2 *pb) { static char name[256]; sprintf(name, "Foot Surface (%s)", plArmatureEffectsMgr::SurfaceStrings[pb->GetInt(ParamID(kSurface))]); return name; } plMessage *plResponderCmdFootSurface::CreateMsg(plMaxNode* node, plErrorMsg *pErrMsg, IParamBlock2 *pb) { plArmatureEffectStateMsg* msg = TRACKED_NEW plArmatureEffectStateMsg; msg->SetBCastFlag(plMessage::kPropagateToModifiers); msg->SetBCastFlag(plMessage::kNetPropagate); msg->fSurface = pb->GetInt(kSurface); return msg; } class plResponderFootSurfaceProc : public ParamMap2UserDlgProc { public: BOOL DlgProc(TimeValue t, IParamMap2 *pm, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { IParamBlock2 *pb = pm->GetParamBlock(); HWND hCB = GetDlgItem(hWnd, IDC_COMP_RESPOND_FOOT_SURFACE); int i; switch (msg) { case WM_INITDIALOG: for (i = 0; i < plArmatureEffectsMgr::kMaxSurface; i++) ComboBox_AddString(hCB, plArmatureEffectsMgr::SurfaceStrings[i]); ComboBox_SetCurSel(hCB, pb->GetInt(ParamID(kSurface))); return TRUE; case WM_COMMAND: if (HIWORD(wParam) == CBN_SELCHANGE && LOWORD(wParam) == IDC_COMP_RESPOND_FOOT_SURFACE) pb->SetValue(ParamID(kSurface), 0, ComboBox_GetCurSel(hCB)); } return FALSE; } void DeleteThis() {} }; static plResponderFootSurfaceProc gResponderFootSurfaceProc; /////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////// #include "plMultistageBehComponent.h" class plResponderMultistageProc; extern plResponderMultistageProc gResponderMultistageProc; enum { kMultistageComp, kMultistageNode }; ParamBlockDesc2 gResponderMultistageBlock ( kResponderMultistageBlk, _T("multistage"), 0, NULL, P_AUTO_UI, IDD_COMP_RESPOND_ONESHOT, IDS_COMP_CMD_PARAMS, 0, 0, &gResponderMultistageProc, kMultistageComp, _T("comp"), TYPE_INODE, 0, 0, end, kMultistageNode, _T("node"), TYPE_INODE, 0, 0, end, end ); plResponderCmdMultistage& plResponderCmdMultistage::Instance() { static plResponderCmdMultistage theInstance; return theInstance; } ParamBlockDesc2 *plResponderCmdMultistage::GetDesc() { return &gResponderMultistageBlock; } const char *plResponderCmdMultistage::GetInstanceName(IParamBlock2 *pb) { static char name[256]; INode *node = pb->GetINode(kMultistageComp); sprintf(name, "Multistage (%s)", node ? node->GetName() : "none"); return name; } plMessage *plResponderCmdMultistage::CreateMsg(plMaxNode* node, plErrorMsg *pErrMsg, IParamBlock2 *pb) { plResponderCompNode compNode; plResponderCompNode::ClassIDs cids; cids.push_back(MULTISTAGE_BEH_CID); compNode.Init(pb, kMultistageComp, kMultistageNode, IDC_RESPONDER_COMP, IDC_RESPONDER_NODE, &cids); plComponentBase *comp; plMaxNodeBase *targNode; if (compNode.GetCompAndNode(comp, targNode)) { plNotifyMsg* msg = TRACKED_NEW plNotifyMsg; msg->SetState(1.f); // Will actually be set to the player key at runtime plKey playerKey, self; msg->AddCollisionEvent(true, playerKey, self); plKey multiKey = MultiStageBeh::GetMultiStageBehKey(comp, targNode); msg->AddReceiver(multiKey); return msg; } else throw "No Multistage component specified"; } class plResponderMultistageProc : public ParamMap2UserDlgProc { protected: plResponderCompNode fCompNode; public: BOOL DlgProc(TimeValue t, IParamMap2 *pm, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_INITDIALOG: { IParamBlock2 *pb = pm->GetParamBlock(); plResponderCompNode::ClassIDs cids; cids.push_back(MULTISTAGE_BEH_CID); fCompNode.Init(pb, kMultistageComp, kMultistageNode, IDC_RESPONDER_COMP, IDC_RESPONDER_NODE, &cids); fCompNode.InitDlg(hWnd); } return TRUE; case WM_COMMAND: if (HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDC_RESPONDER_COMP) { fCompNode.CompButtonPress(hWnd); return TRUE; } else if (HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDC_RESPONDER_NODE) { fCompNode.NodeButtonPress(hWnd); return TRUE; } break; } return FALSE; } void DeleteThis() {} }; static plResponderMultistageProc gResponderMultistageProc;