|
|
|
/*==LICENSE==*
|
|
|
|
|
|
|
|
CyanWorlds.com Engine - MMOG client, server and tools
|
|
|
|
Copyright (C) 2011 Cyan Worlds, Inc.
|
|
|
|
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
Additional permissions under GNU GPL version 3 section 7
|
|
|
|
|
|
|
|
If you modify this Program, or any covered work, by linking or
|
|
|
|
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
|
|
|
|
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
|
|
|
|
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
|
|
|
|
(or a modified version of those libraries),
|
|
|
|
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
|
|
|
|
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
|
|
|
|
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
|
|
|
|
licensors of this Program grant you additional
|
|
|
|
permission to convey the resulting work. Corresponding Source for a
|
|
|
|
non-source form of such a combination shall include the source code for
|
|
|
|
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
|
|
|
|
work.
|
|
|
|
|
|
|
|
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
|
|
|
or by snail mail at:
|
|
|
|
Cyan Worlds, Inc.
|
|
|
|
14617 N Newport Hwy
|
|
|
|
Mead, WA 99021
|
|
|
|
|
|
|
|
*==LICENSE==*/
|
|
|
|
#include "HeadSpin.h"
|
|
|
|
#include "max.h"
|
|
|
|
#include "resource.h" // Resource Dependencies
|
|
|
|
|
|
|
|
#include "MaxMain/plPhysicalProps.h"
|
|
|
|
|
|
|
|
#include "plComponent.h" //Component Dependencies
|
|
|
|
#include "plComponentReg.h" // Ibid
|
|
|
|
#include "MaxMain/plMaxNode.h" // Ibid
|
|
|
|
#include "pnKeyedObject/plKey.h" // Ibid
|
|
|
|
#include "plComponentProcBase.h"
|
|
|
|
|
|
|
|
#include "plNavigableComponents.h"
|
|
|
|
#include "plActivatorBaseComponent.h"
|
|
|
|
#include "plPhysicalComponents.h"
|
|
|
|
|
|
|
|
#include "MaxConvert/hsConverterUtils.h" //Conversion Dependencies
|
|
|
|
#include "MaxConvert/hsControlConverter.h" // Ibid
|
|
|
|
|
|
|
|
#include "plAvatar/plAvLadderModifier.h" //Modifier Dependencies
|
|
|
|
#include "plPhysical/plSimDefs.h"
|
|
|
|
|
|
|
|
#include "plgDispatch.h" //Message Dependencies
|
|
|
|
#include "pnMessage/plObjRefMsg.h" // Ibid
|
|
|
|
#include "pnMessage/plIntRefMsg.h" // Ibid
|
|
|
|
#include "pnMessage/plNodeRefMsg.h" // Ibid
|
|
|
|
#include "MaxMain/plPlasmaRefMsgs.h" // Ibid
|
|
|
|
|
|
|
|
void DummyCodeIncludeFuncNavigablesRegion() {}
|
|
|
|
|
|
|
|
|
|
|
|
CLASS_DESC(plAvLadderComponent, gAvLadderComponentDesc, "(ex)Ladder Component", "(ex)LadderComp", COMP_TYPE_PHYS_TERRAINS, NAV_LADDER_CID)
|
|
|
|
|
|
|
|
enum kAvLadderFields
|
|
|
|
{
|
|
|
|
kTypeCombo,
|
|
|
|
kLoopsInt,
|
|
|
|
kTriggerNode,
|
|
|
|
kDirectionBool,
|
|
|
|
kBoundsType_DEAD,
|
|
|
|
kEnabled,
|
|
|
|
kLadderNode,
|
|
|
|
};
|
|
|
|
|
|
|
|
class plAvLadderComponentProc : public ParamMap2UserDlgProc
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
enum kLadderTypesEnums
|
|
|
|
{
|
|
|
|
kReallyBig,
|
|
|
|
kFourFeet,
|
|
|
|
kTwoFeet,
|
|
|
|
};
|
|
|
|
|
|
|
|
BOOL DlgProc(TimeValue t, IParamMap2 *map, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|
|
|
{
|
|
|
|
switch (msg)
|
|
|
|
{
|
|
|
|
case WM_INITDIALOG:
|
|
|
|
{
|
|
|
|
HWND hLadder = GetDlgItem(hWnd,IDC_COMP_NAV_LADDER_COMBO);
|
|
|
|
|
|
|
|
ComboBox_AddString(hLadder, "Big");
|
|
|
|
ComboBox_AddString(hLadder, "4 feet");
|
|
|
|
ComboBox_AddString(hLadder, "2 feet");
|
|
|
|
|
|
|
|
int type = map->GetParamBlock()->GetInt(kTypeCombo);
|
|
|
|
ComboBox_SetCurSel(hLadder, type);
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
case WM_COMMAND:
|
|
|
|
if (LOWORD(wParam) == IDC_COMP_NAV_LADDER_COMBO && HIWORD(wParam) == CBN_SELCHANGE)
|
|
|
|
{
|
|
|
|
//Util fcn found in plEventGroupRefs files in MaxMain
|
|
|
|
HWND hLadder = GetDlgItem(hWnd,IDC_COMP_NAV_LADDER_COMBO);
|
|
|
|
int idx = ComboBox_GetCurSel(hLadder);
|
|
|
|
map->GetParamBlock()->SetValue(kTypeCombo, 0, idx);
|
|
|
|
/*
|
|
|
|
if (idx == kReallyBig)
|
|
|
|
{
|
|
|
|
map->Enable(kLoopsInt, TRUE);
|
|
|
|
// map->Invalidate(kLoopsInt);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
map->Enable(kLoopsInt, TRUE);
|
|
|
|
// map->Invalidate(kLoopsInt);
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void DeleteThis() {}
|
|
|
|
};
|
|
|
|
static plAvLadderComponentProc gAvLadderComponentProc;
|
|
|
|
|
|
|
|
ParamBlockDesc2 gAvLadderComponentBlock
|
|
|
|
(
|
|
|
|
plComponent::kBlkComp, _T("(ex)Ladder Component"), 0, &gAvLadderComponentDesc, P_AUTO_CONSTRUCT + P_AUTO_UI, plComponent::kRefComp,
|
|
|
|
|
|
|
|
IDD_COMP_NAV_LADDER, IDS_COMP_NAV_LADDERS, 0, 0, &gAvLadderComponentProc,
|
|
|
|
|
|
|
|
kTypeCombo, _T("Ladder Type"), TYPE_INT, 0,0,
|
|
|
|
end,
|
|
|
|
|
|
|
|
kDirectionBool, _T("Climbing Direction"), TYPE_INT, 0, 0,
|
|
|
|
p_ui, TYPE_RADIO, 2, IDC_RADIO_UP, IDC_RADIO_DOWN,
|
|
|
|
p_vals, true, false,
|
|
|
|
end,
|
|
|
|
|
|
|
|
kLoopsInt, _T("BigLadderNumLoop"), TYPE_INT, 0, 0,
|
|
|
|
p_default, 0,
|
|
|
|
p_range, 0, 500,
|
|
|
|
p_ui, TYPE_SPINNER, EDITTYPE_INT,
|
|
|
|
IDC_COMP_NAV_LADDER_LOOPS_EDIT, IDC_COMP_NAV_LADDER_LOOPS_SPIN, 0.4,
|
|
|
|
end,
|
|
|
|
|
|
|
|
kTriggerNode, _T("Trigger Node"), TYPE_INODE, 0, 0,
|
|
|
|
p_ui, TYPE_PICKNODEBUTTON, IDC_COMP_NAV_TRIGGER,
|
|
|
|
//p_sclassID, GEOMOBJECT_CLASS_ID,
|
|
|
|
p_prompt, IDS_COMP_PHYS_CHOSEN_BASE,
|
|
|
|
//p_accessor, &gPhysCoreAccessor,
|
|
|
|
end,
|
|
|
|
|
|
|
|
kLadderNode, _T("ladder"), TYPE_INODE, 0, 0,
|
|
|
|
p_ui, TYPE_PICKNODEBUTTON, IDC_COMP_NAV_LADDER,
|
|
|
|
end,
|
|
|
|
|
|
|
|
kEnabled, _T("enabled"), TYPE_BOOL, 0, 0,
|
|
|
|
p_ui, TYPE_SINGLECHEKBOX, IDC_ENABLED,
|
|
|
|
p_default, TRUE,
|
|
|
|
end,
|
|
|
|
|
|
|
|
end
|
|
|
|
);
|
|
|
|
|
|
|
|
plAvLadderComponent::plAvLadderComponent()
|
|
|
|
{
|
|
|
|
fClassDesc = &gAvLadderComponentDesc;
|
|
|
|
fClassDesc->MakeAutoParamBlocks(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
void plAvLadderComponent::CollectNonDrawables(INodeTab& nonDrawables)
|
|
|
|
{
|
|
|
|
INode* ladderNode = fCompPB->GetINode(kLadderNode);
|
|
|
|
if( ladderNode )
|
|
|
|
nonDrawables.Append(1, &ladderNode);
|
|
|
|
|
|
|
|
INode* triggerNode = fCompPB->GetINode(kTriggerNode);
|
|
|
|
if( triggerNode )
|
|
|
|
nonDrawables.Append(1, &triggerNode);
|
|
|
|
|
|
|
|
AddTargetsToList(nonDrawables);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool plAvLadderComponent::SetupProperties(plMaxNode *node, plErrorMsg *pErrMsg)
|
|
|
|
{
|
|
|
|
fKeys.Reset();
|
|
|
|
|
|
|
|
//
|
|
|
|
// Create an invisible blocker for the ladder shape, so the avatar won't fall over the side
|
|
|
|
//
|
|
|
|
plMaxNode *ladderNode = (plMaxNode*)fCompPB->GetINode(kLadderNode);
|
|
|
|
if (ladderNode)
|
|
|
|
{
|
|
|
|
plPhysicalProps* ladderPhys = ladderNode->GetPhysicalProps();
|
|
|
|
// ladderPhys->SetMass(0, ladderNode, pErrMsg);
|
|
|
|
ladderPhys->SetBoundsType(plSimDefs::kHullBounds, ladderNode, pErrMsg);
|
|
|
|
ladderPhys->SetGroup(plSimDefs::kGroupStatic, ladderNode, pErrMsg);
|
|
|
|
/// ladderPhys->SetAllowLOS(true, ladderNode, pErrMsg);
|
|
|
|
|
|
|
|
ladderNode->SetDrawable(false);
|
|
|
|
ladderNode->SetForceLocal(true); // Get a coord interface for facing calculations
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pErrMsg->Set(true,
|
|
|
|
"Ladder Warning",
|
|
|
|
"Ladder component %s doesn't have the ladder node set",
|
|
|
|
GetINode()->GetName()).Show();
|
|
|
|
pErrMsg->Set(false);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Create a detector region for the node we're attached to
|
|
|
|
//
|
|
|
|
plPhysicalProps *physProps = node->GetPhysicalProps();
|
|
|
|
|
|
|
|
plMaxNode *triggerNode = (plMaxNode*)fCompPB->GetINode(kTriggerNode);
|
|
|
|
if (triggerNode)
|
|
|
|
physProps->SetProxyNode(triggerNode, node, pErrMsg);
|
|
|
|
|
|
|
|
physProps->SetGroup(plSimDefs::kGroupDetector, node, pErrMsg); // this is a detector
|
|
|
|
physProps->SetReportGroup(1<<plSimDefs::kGroupAvatar, node, pErrMsg); // only fires on local avatars
|
|
|
|
physProps->SetPinned(true, node, pErrMsg);
|
|
|
|
// only if movable will it have mass (then it will keep track of movements in PhysX)
|
|
|
|
if ( node->IsMovable() || node->IsTMAnimated() )
|
|
|
|
physProps->SetMass(1.0f, node, pErrMsg); // detectors don't move
|
|
|
|
physProps->SetBoundsType(plSimDefs::kHullBounds, node, pErrMsg);
|
|
|
|
|
|
|
|
node->SetForceLocal(true); // force our seek point to be local
|
|
|
|
node->SetDrawable(false);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool plAvLadderComponent::PreConvert(plMaxNode *node, plErrorMsg *pErrMsg)
|
|
|
|
{
|
|
|
|
plMaxNode *ladderNode = (plMaxNode*)fCompPB->GetINode(kLadderNode);
|
|
|
|
if (!ladderNode)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
plMaxNode *triggerNode = (plMaxNode*)fCompPB->GetINode(kTriggerNode);
|
|
|
|
if (!triggerNode)
|
|
|
|
triggerNode = node;
|
|
|
|
|
|
|
|
// Get a vector pointing from the ladder to the detector, for facing calculations
|
|
|
|
Point3 ladderViewMax = ladderNode->GetNodeTM(0).GetTrans() - triggerNode->GetNodeTM(0).GetTrans();
|
|
|
|
hsVector3 ladderView(ladderViewMax.x, ladderViewMax.y, ladderViewMax.z);
|
|
|
|
ladderView.fZ = 0;
|
|
|
|
ladderView.Normalize();
|
|
|
|
|
|
|
|
bool goingUp = (fCompPB->GetInt(kDirectionBool) != 0);
|
|
|
|
int loops = fCompPB->GetInt(kLoopsInt);
|
|
|
|
int ladderType = fCompPB->GetInt(kTypeCombo);
|
|
|
|
bool enabled = (fCompPB->GetInt(kEnabled) != 0);
|
|
|
|
|
|
|
|
plAvLadderMod* ladMod = new plAvLadderMod(goingUp, ladderType, loops, enabled, ladderView);
|
|
|
|
plKey modKey = node->AddModifier(ladMod, IGetUniqueName(node));
|
|
|
|
fKeys.Append(modKey);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool plAvLadderComponent::Convert(plMaxNode *node, plErrorMsg *pErrMsg)
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool plAvLadderComponent::DeInit(plMaxNode *node, plErrorMsg *pErrMsg)
|
|
|
|
{
|
|
|
|
fKeys.Reset();
|
|
|
|
return true;
|
|
|
|
}
|