1
0
mirror of https://foundry.openuru.org/gitblit/r/CWE-ou-minkata.git synced 2025-07-20 04:09:16 +00:00

Initial Commit of CyanWorlds.com Engine Open Source Client/Plugin

This commit is contained in:
JWPlatt
2011-03-12 12:34:52 -05:00
commit a20a222fc2
3976 changed files with 1301355 additions and 0 deletions

View File

@ -0,0 +1,127 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "plAnimEventModifier.h"
#include "hsResMgr.h"
#include "../pnMessage/plMessage.h"
#include "../pnMessage/plRefMsg.h"
#include "../pnMessage/plEnableMsg.h"
#include "../pnMessage/plEventCallbackMsg.h"
plAnimEventModifier::plAnimEventModifier() : fCallback(nil), fDisabled(false)
{
}
plAnimEventModifier::~plAnimEventModifier()
{
hsRefCnt_SafeUnRef(fCallback);
}
void plAnimEventModifier::Read(hsStream* stream, hsResMgr* mgr)
{
plSingleModifier::Read(stream, mgr);
int numReceivers = stream->ReadSwap32();
fReceivers.Expand(numReceivers);
for (int i = 0; i < numReceivers; i++)
fReceivers.Push(mgr->ReadKey(stream));
fCallback = plMessage::ConvertNoRef(mgr->ReadCreatable(stream));
//
// Create a passive ref to the animation controller. Then, when we're
// notified that it's loaded we can send our callback setup message.
//
plKey animKey = fCallback->GetReceiver(0);
hsgResMgr::ResMgr()->AddViaNotify(animKey,
TRACKED_NEW plGenRefMsg(GetKey(), plRefMsg::kOnCreate, 0, 0),
plRefFlags::kPassiveRef);
}
void plAnimEventModifier::Write(hsStream* stream, hsResMgr* mgr)
{
plSingleModifier::Write(stream, mgr);
int numReceivers = fReceivers.Count();
stream->WriteSwap32(numReceivers);
for (int i = 0; i < numReceivers; i++)
mgr->WriteKey(stream, fReceivers[i]);
mgr->WriteCreatable(stream, fCallback);
}
hsBool plAnimEventModifier::MsgReceive(plMessage* msg)
{
// Assuming we only have one ref, the anim time convert. When it loads, we
// send our callback setup message.
plGenRefMsg* genRefMsg = plGenRefMsg::ConvertNoRef(msg);
if (genRefMsg && (genRefMsg->GetContext() & plRefMsg::kOnCreate) && fCallback)
{
hsRefCnt_SafeRef(fCallback);
fCallback->Send();
}
plEventCallbackMsg* callbackMsg = plEventCallbackMsg::ConvertNoRef(msg);
if (callbackMsg)
{
ISendNotify(true);
ISendNotify(false);
}
plEnableMsg* pEnable = plEnableMsg::ConvertNoRef(msg);
if (pEnable)
{
if (pEnable->Cmd(plEnableMsg::kDisable))
fDisabled = true;
else
if (pEnable->Cmd(plEnableMsg::kEnable))
fDisabled = false;
return true;
}
return plSingleModifier::MsgReceive(msg);
}
#include "../pnNetCommon/plNetApp.h"
#include "../pnMessage/plNotifyMsg.h"
void plAnimEventModifier::ISendNotify(bool triggered)
{
if (fDisabled)
return;
plNotifyMsg* notify = TRACKED_NEW plNotifyMsg;
// Setup the event data in case this is a OneShot responder that needs it
plKey playerKey = plNetClientApp::GetInstance()->GetLocalPlayerKey();
notify->AddPickEvent(playerKey, nil, true, hsPoint3(0,0,0) );
notify->SetSender(GetKey());
notify->AddReceivers(fReceivers);
notify->SetState(triggered ? 1.0f : 0.0f);
// these should never need to net propagate...
notify->SetBCastFlag(plMessage::kNetPropagate, false);
notify->Send();
}

View File

@ -0,0 +1,62 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plAnimEventModifier_h_inc
#define plAnimEventModifier_h_inc
#include "../pnModifier/plSingleModifier.h"
#include "hsTemplates.h"
//
// Detects an anim event (marker, begin, end) and sends out a notification.
//
class plAnimEventModifier : public plSingleModifier
{
protected:
hsTArray<plKey> fReceivers;// Keys to notify when the anim event happens
plMessage* fCallback; // The callback setup message we send when the anim loads
virtual hsBool IEval(double secs, hsScalar del, UInt32 dirty) { return false; }
void ISendNotify(bool triggered);
hsBool fDisabled;
public:
plAnimEventModifier();
virtual ~plAnimEventModifier();
CLASSNAME_REGISTER(plAnimEventModifier);
GETINTERFACE_ANY(plAnimEventModifier, plSingleModifier);
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
virtual hsBool MsgReceive(plMessage* msg);
// Export only
void SetReceivers(hsTArray<plKey>& receivers) { fReceivers = receivers; }
void SetCallback(plMessage* callback) { fCallback = callback; }
};
#endif // plAnimEventModifier_h_inc

View File

@ -0,0 +1,127 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "hsTimer.h"
#include "plAnimTimeConvertSDLModifier.h"
#include "../plSDL/plSDL.h"
#include "../plInterp/plAnimTimeConvert.h"
// static vars
char plAnimTimeConvertSDLModifier::AnimTimeConvertVarNames::kStrFlags[]="flags";
char plAnimTimeConvertSDLModifier::AnimTimeConvertVarNames::kStrLastStateAnimTime[]="lastStateAnimTime";
char plAnimTimeConvertSDLModifier::AnimTimeConvertVarNames::kStrLoopBegin[]="loopBegin";
char plAnimTimeConvertSDLModifier::AnimTimeConvertVarNames::kStrLoopEnd[]="loopEnd";
char plAnimTimeConvertSDLModifier::AnimTimeConvertVarNames::kStrSpeed[]="speed";
char plAnimTimeConvertSDLModifier::AnimTimeConvertVarNames::kStrCurrentEaseCurve[]="currentEaseCurve";
char plAnimTimeConvertSDLModifier::AnimTimeConvertVarNames::kStrCurrentEaseBeginWorldTime[]="currentEaseBeginWorldTime";
char plAnimTimeConvertSDLModifier::AnimTimeConvertVarNames::kStrLastStateChange[]="lastStateChange";
//
// Copy atcs from current state into sdl
//
void plAnimTimeConvertSDLModifier::IPutATC(plStateDataRecord* atcStateDataRec, plAnimTimeConvert* animTimeConvert)
{
plATCState *lastState = animTimeConvert->fStates.front();
atcStateDataRec->FindVar(AnimTimeConvertVarNames::kStrFlags)->Set(animTimeConvert->fFlags);
atcStateDataRec->FindVar(AnimTimeConvertVarNames::kStrLastStateAnimTime)->Set(lastState->fStartAnimTime);
atcStateDataRec->FindVar(AnimTimeConvertVarNames::kStrLoopEnd)->Set(animTimeConvert->fLoopEnd);
atcStateDataRec->FindVar(AnimTimeConvertVarNames::kStrLoopBegin)->Set(animTimeConvert->fLoopBegin);
atcStateDataRec->FindVar(AnimTimeConvertVarNames::kStrSpeed)->Set(animTimeConvert->fSpeed);
atcStateDataRec->FindVar(AnimTimeConvertVarNames::kStrLastStateChange)->Set(lastState->fStartWorldTime);
int curEaseCurve = animTimeConvert->GetCurrentEaseCurve();
atcStateDataRec->FindVar(AnimTimeConvertVarNames::kStrCurrentEaseCurve)->Set(curEaseCurve);
atcStateDataRec->FindVar(AnimTimeConvertVarNames::kStrCurrentEaseBeginWorldTime)->Set(curEaseCurve ?
animTimeConvert->fCurrentEaseCurve->fBeginWorldTime : 0);
}
//
// Apply state in SDL record to current animation state
//
//#include "../pnSceneObject/plSceneObject.h"
void plAnimTimeConvertSDLModifier::ISetCurrentATC(const plStateDataRecord* atcStateDataRec, plAnimTimeConvert* objAtc)
{
// if ( GetTarget(0)->GetKeyName() && stricmp( GetTarget(0)->GetKeyName(), "RTDirLight01" )==0 )
// {
// int xx=0;
// }
if (atcStateDataRec->IsUsed())
{
plStateDataRecord::SimpleVarsList vars;
int num=atcStateDataRec->GetUsedVars(&vars);
int j;
hsScalar lastStateAnimTime = 0;
double lastStateChange = 0;
for(j=0;j<num;j++)
{
if (vars[j]->IsNamed(AnimTimeConvertVarNames::kStrFlags))
{
int f;
vars[j]->Get(&f);
objAtc->fFlags=f;
}
else
if (vars[j]->IsNamed(AnimTimeConvertVarNames::kStrLastStateAnimTime))
vars[j]->Get(&lastStateAnimTime);
else
if (vars[j]->IsNamed(AnimTimeConvertVarNames::kStrLoopBegin))
vars[j]->Get(&objAtc->fLoopBegin);
else
if (vars[j]->IsNamed(AnimTimeConvertVarNames::kStrLoopEnd))
vars[j]->Get(&objAtc->fLoopEnd);
else
if (vars[j]->IsNamed(AnimTimeConvertVarNames::kStrSpeed))
vars[j]->Get(&objAtc->fSpeed);
else
if (vars[j]->IsNamed(AnimTimeConvertVarNames::kStrLastStateChange))
vars[j]->Get(&lastStateChange);
else
if (vars[j]->IsNamed(AnimTimeConvertVarNames::kStrCurrentEaseCurve))
{
int ces;
vars[j]->Get(&ces);
if (ces == plAnimTimeConvert::kEaseSpeed)
{
// I don't think this ever happens in practice. If it becomes necessary,
// we can work around it. But unless it's actually used, I don't want
// to waste the space storing a speed ease curve.
objAtc->SetCurrentEaseCurve(plAnimTimeConvert::kEaseNone);
}
else
objAtc->SetCurrentEaseCurve(ces); // The ATC will ignore an index out of range
}
else
if (vars[j]->IsNamed(AnimTimeConvertVarNames::kStrCurrentEaseBeginWorldTime) && objAtc->fCurrentEaseCurve)
vars[j]->Get(&objAtc->fCurrentEaseCurve->fBeginWorldTime);
}
objAtc->IClearAllStates();
objAtc->IProcessStateChange(lastStateChange, lastStateAnimTime);
objAtc->fCurrentAnimTime = lastStateAnimTime;
objAtc->fLastEvalWorldTime = lastStateChange;
objAtc->SetFlag(plAnimTimeConvert::kForcedMove, true);
}
}

View File

@ -0,0 +1,63 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plAnimTimeConvertSDLModifier_inc
#define plAnimTimeConvertSDLModifier_inc
#include "../plModifier/plSDLModifier.h"
//
// This modifier (abstract baseclass) handles sending and recving
// the state for an animTimeConvert
//
class plStateDataRecord;
class plAnimTimeConvert;
class plAnimTimeConvertSDLModifier : public plSDLModifier
{
protected:
// var labels
struct AnimTimeConvertVarNames
{
static char kStrFlags[];
static char kStrLastStateAnimTime[];
static char kStrLoopBegin[];
static char kStrLoopEnd[];
static char kStrSpeed[];
static char kStrCurrentEaseCurve[];
static char kStrCurrentEaseBeginWorldTime[];
static char kStrLastStateChange[];
};
void IPutATC(plStateDataRecord* state, plAnimTimeConvert* curAnimTimeConvert);
void ISetCurrentATC(const plStateDataRecord* state, plAnimTimeConvert* curAnimTimeConvert);
public:
CLASSNAME_REGISTER( plAnimTimeConvertSDLModifier);
GETINTERFACE_ANY( plAnimTimeConvertSDLModifier, plSDLModifier);
};
#endif // plAnimTimeConvertSDLModifier_inc

View File

@ -0,0 +1,373 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "hsTypes.h"
#include "hsUtils.h"
#include "plAxisAnimModifier.h"
#include "hsResMgr.h"
#include "../pnSceneObject/plSceneObject.h"
#include "../pnKeyedObject/plKey.h"
#include "../plNetMessage/plNetMsgHelpers.h"
#include "../pnMessage/plNotifyMsg.h"
#include "../pnMessage/plTimeMsg.h"
#include "../pnMessage/plCmdIfaceModMsg.h"
#include "../plMessage/plAnimCmdMsg.h"
#include "../plMessage/plInputEventMsg.h"
#include "../plMessage/plInputIfaceMgrMsg.h"
#include "../plInputCore/plInputDevice.h"
#include "../plInputCore/plInputManager.h"
#include "../plInputCore/plInputInterface.h"
#include "../pnNetCommon/plNetApp.h"
#include "plgDispatch.h"
//// plAxisInputInterface ////////////////////////////////////////////////////
// Small input interface to handle mouse imput while dragging. Supercedes
// the sceneInteraction Interface
class plAxisInputInterface : public plInputInterface
{
protected:
plAxisAnimModifier *fOwner;
virtual ControlEventCode *IGetOwnedCodeList( void ) const
{
static ControlEventCode codes[] = { END_CONTROLS };
return codes;
}
public:
plAxisInputInterface( plAxisAnimModifier *owner ) { fOwner = owner; SetEnabled( true ); }
virtual UInt32 GetPriorityLevel( void ) const { return kSceneInteractionPriority + 10; }
virtual hsBool InterpretInputEvent( plInputEventMsg *pMsg )
{
plMouseEventMsg* pMMsg = plMouseEventMsg::ConvertNoRef( pMsg );
if (pMMsg )
{
if( pMMsg->GetButton() == kLeftButtonUp )
{
// Remove ourselves from the stack
plInputIfaceMgrMsg *msg = TRACKED_NEW plInputIfaceMgrMsg( plInputIfaceMgrMsg::kRemoveInterface );
msg->SetIFace( this );
plgDispatch::MsgSend( msg );
return true;
}
return fOwner->MsgReceive( pMMsg );
}
return false;
}
virtual UInt32 GetCurrentCursorID( void ) const { return kCursorGrab; }
virtual hsBool HasInterestingCursorID( void ) const { return true; }
};
plAxisAnimModifier::plAxisAnimModifier() :
fXAnim(nil),
fYAnim(nil),
fActive(false),
fXPos(0.0f),
fYPos(0.0f),
fIface(0),
fAllOrNothing(false)
{
fNotify = TRACKED_NEW plNotifyMsg;
fInputIface = TRACKED_NEW plAxisInputInterface( this );
}
plAxisAnimModifier::~plAxisAnimModifier()
{
hsRefCnt_SafeUnRef(fNotify);
hsRefCnt_SafeUnRef( fInputIface );
}
hsBool plAxisAnimModifier::IEval(double secs, hsScalar del, UInt32 dirty)
{
if (!fActive)
return true;
return true;
}
void plAxisAnimModifier::SetTarget(plSceneObject* so)
{
plSingleModifier::SetTarget(so);
if( so )
plgDispatch::Dispatch()->RegisterForExactType(plEvalMsg::Index(), GetKey());
}
hsBool plAxisAnimModifier::MsgReceive(plMessage* msg)
{
plEventCallbackMsg* pCall = plEventCallbackMsg::ConvertNoRef(msg);
if (pCall)
{
// Send our notification to whomever cares;
hsScalar time = 0.0f;
if (pCall->fEvent == kEnd)
time = 1.0f;
fNotify->ClearEvents();
fNotify->SetSender(fNotificationKey); // so python can handle it.
fNotify->AddCallbackEvent( pCall->fEvent );
fNotify->SetState(1.0f);
fNotify->AddActivateEvent(true);
fNotify->AddClickDragEvent(GetTarget()->GetKey(), plNetClientApp::GetInstance()->GetLocalPlayerKey(), time);
hsRefCnt_SafeRef(fNotify);
plgDispatch::MsgSend( fNotify );
return true;
}
plNotifyMsg* pNMsg = plNotifyMsg::ConvertNoRef(msg);
if (pNMsg)
{
for (int i = 0; i < pNMsg->GetEventCount(); i++)
{
if (pNMsg->GetEventRecord(i)->fEventType == proEventData::kActivate)
{
if( ( (proActivateEventData *)pNMsg->GetEventRecord(i) )->fActivate )
{
fActive = true;
fXPos = plMouseDevice::Instance()->GetCursorX();
fYPos = plMouseDevice::Instance()->GetCursorY();
// Insert our input interface onto the input stack
plInputIfaceMgrMsg *msg = TRACKED_NEW plInputIfaceMgrMsg( plInputIfaceMgrMsg::kAddInterface );
msg->SetIFace( fInputIface );
plgDispatch::MsgSend( msg );
}
else
{
/* if (fActive)
{
fActive = false;
// Remove our input interface from the input stack
plInputIfaceMgrMsg *msg = TRACKED_NEW plInputIfaceMgrMsg( plInputIfaceMgrMsg::kRemoveInterface );
msg->SetIFace( fInputIface );
plgDispatch::MsgSend( msg );
}
*/ }
break;
}
}
return true;
}
plMouseEventMsg* pMMsg = plMouseEventMsg::ConvertNoRef(msg);
if (pMMsg)
{
if (fXAnim && pMMsg->GetDX() != 0.0f)
{
if (pMMsg->GetDX() > 0.05f)
return true;
plAnimCmdMsg* pMsg = TRACKED_NEW plAnimCmdMsg;
pMsg->AddReceiver(fXAnim);
pMsg->SetAnimName(fAnimLabel.c_str());
// pMsg->SetAnimName()
if (fXPos < pMMsg->GetXPos())
{
pMsg->SetCmd(plAnimCmdMsg::kIncrementForward);
}
else
{
pMsg->SetCmd(plAnimCmdMsg::kIncrementBackward);
}
plgDispatch::MsgSend(pMsg);
fXPos = pMMsg->GetXPos();
}
if (fYAnim && pMMsg->GetDY() != 0.0f)
{
if (pMMsg->GetDY() > 0.05f)
return true;
plAnimCmdMsg* pMsg = TRACKED_NEW plAnimCmdMsg;
pMsg->AddReceiver(fYAnim);
pMsg->SetAnimName(fAnimLabel.c_str());
if (fYPos > pMMsg->GetYPos())
{
if (fAllOrNothing)
{
pMsg->SetCmd(plAnimCmdMsg::kContinue);
pMsg->SetCmd(plAnimCmdMsg::kSetForewards);
fActive = false;
// Remove our input interface from the input stack
plInputIfaceMgrMsg *msg = TRACKED_NEW plInputIfaceMgrMsg( plInputIfaceMgrMsg::kRemoveInterface );
msg->SetIFace( fInputIface );
plgDispatch::MsgSend( msg );
plInputManager::SetRecenterMouse(false);
}
else
{
pMsg->SetCmd(plAnimCmdMsg::kIncrementForward);
}
}
else
{
if (fAllOrNothing)
{
pMsg->SetCmd(plAnimCmdMsg::kContinue);
pMsg->SetCmd(plAnimCmdMsg::kSetBackwards);
fActive = false;
// Remove our input interface from the input stack
plInputIfaceMgrMsg *msg = TRACKED_NEW plInputIfaceMgrMsg( plInputIfaceMgrMsg::kRemoveInterface );
msg->SetIFace( fInputIface );
plgDispatch::MsgSend( msg );
plInputManager::SetRecenterMouse(false);
}
else
{
pMsg->SetCmd(plAnimCmdMsg::kIncrementBackward);
}
}
plgDispatch::MsgSend(pMsg);
fYPos = pMMsg->GetYPos();
}
return true;
}
plCmdIfaceModMsg* pCMsg = plCmdIfaceModMsg::ConvertNoRef(msg);
if (pCMsg && pCMsg->Cmd(plCmdIfaceModMsg::kIndexCallback))
{
fIface = pCMsg->fIndex;
return true;
}
plGenRefMsg* pRefMsg = plGenRefMsg::ConvertNoRef(msg);
if (pRefMsg)
{
if (pRefMsg->GetContext() == plRefMsg::kOnCreate )
{
if (pRefMsg->fType == kTypeX)
{
fXAnim = pRefMsg->GetRef()->GetKey();
// add callbacks for beginning and end of animation
plEventCallbackMsg* pCall1 = TRACKED_NEW plEventCallbackMsg;
pCall1->fEvent = kBegin;
pCall1->fRepeats = -1;
pCall1->AddReceiver(GetKey());
plEventCallbackMsg* pCall2 = TRACKED_NEW plEventCallbackMsg;
pCall2->fEvent = kEnd;
pCall2->fRepeats = -1;
pCall2->AddReceiver(GetKey());
plAnimCmdMsg* pMsg = TRACKED_NEW plAnimCmdMsg;
pMsg->SetCmd(plAnimCmdMsg::kAddCallbacks);
pMsg->AddCallback(pCall1);
pMsg->AddCallback(pCall2);
pMsg->SetAnimName(fAnimLabel.c_str());
pMsg->AddReceiver( fXAnim );
hsRefCnt_SafeUnRef( pCall1 );
hsRefCnt_SafeUnRef( pCall2 );
plgDispatch::MsgSend(pMsg);
}
else
if (pRefMsg->fType == kTypeY)
{
fYAnim = pRefMsg->GetRef()->GetKey();
// add callbacks for beginning and end of animation
plEventCallbackMsg* pCall1 = TRACKED_NEW plEventCallbackMsg;
pCall1->fEvent = kBegin;
pCall1->fRepeats = -1;
pCall1->AddReceiver(GetKey());
plEventCallbackMsg* pCall2 = TRACKED_NEW plEventCallbackMsg;
pCall2->fEvent = kEnd;
pCall2->fRepeats = -1;
pCall2->AddReceiver(GetKey());
plAnimCmdMsg* pMsg = TRACKED_NEW plAnimCmdMsg;
pMsg->SetCmd(plAnimCmdMsg::kAddCallbacks);
pMsg->AddCallback(pCall1);
pMsg->AddCallback(pCall2);
pMsg->AddReceiver( fYAnim );
pMsg->SetAnimName(fAnimLabel.c_str());
hsRefCnt_SafeUnRef( pCall1 );
hsRefCnt_SafeUnRef( pCall2 );
plgDispatch::MsgSend(pMsg);
}
else
if (pRefMsg->fType == kTypeLogic)
{
SetNotificationKey(pRefMsg->GetRef());
}
}
else
if (pRefMsg->GetContext() == plRefMsg::kOnDestroy )
{
if (pRefMsg->fType == kTypeX)
fXAnim = nil;
else
if (pRefMsg->fType == kTypeY)
fYAnim = nil;
else
if (pRefMsg->fType == kTypeLogic)
fNotificationKey = nil;
}
return true;
}
return plSingleModifier::MsgReceive(msg);
}
void plAxisAnimModifier::Read(hsStream* s, hsResMgr* mgr)
{
plSingleModifier::Read(s, mgr);
mgr->ReadKeyNotifyMe( s, TRACKED_NEW plGenRefMsg(GetKey(), plRefMsg::kOnCreate, 0, kTypeX), plRefFlags::kPassiveRef);
mgr->ReadKeyNotifyMe( s, TRACKED_NEW plGenRefMsg(GetKey(), plRefMsg::kOnCreate, 0, kTypeY), plRefFlags::kPassiveRef);
mgr->ReadKeyNotifyMe( s, TRACKED_NEW plGenRefMsg(GetKey(), plRefMsg::kOnCreate, 0, kTypeLogic), plRefFlags::kPassiveRef);
fAllOrNothing = s->ReadBool();
plNotifyMsg* pMsg = plNotifyMsg::ConvertNoRef(mgr->ReadCreatable(s));
if (fNotify)
delete(fNotify);
fNotify = pMsg;
plMsgStdStringHelper::Peek(fAnimLabel, s);
}
void plAxisAnimModifier::Write(hsStream* s, hsResMgr* mgr)
{
plSingleModifier::Write(s, mgr);
mgr->WriteKey(s, fXAnim);
mgr->WriteKey(s, fYAnim);
mgr->WriteKey(s, fNotificationKey);
s->WriteBool(fAllOrNothing);
mgr->WriteCreatable(s, fNotify);
plMsgStdStringHelper::Poke(fAnimLabel, s);
}

View File

@ -0,0 +1,92 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plAxisAnimMod_inc
#define plAxisAnimMod_inc
#include "hsStlUtils.h"
#include "../pnModifier/plSingleModifier.h"
class plKey;
class plNotifyMsg;
class plAxisInputInterface;
class plAxisAnimModifier : public plSingleModifier
{
public:
enum
{
kTypeX,
kTypeY,
kTypeLogic,
};
protected:
plKey fXAnim;
plKey fYAnim;
plKey fNotificationKey;
hsScalar fXPos;
hsScalar fYPos;
hsBool fActive;
hsBool fAllOrNothing;
int fIface;
plNotifyMsg* fNotify;
std::string fAnimLabel;
plAxisInputInterface *fInputIface;
virtual hsBool IEval(double secs, hsScalar del, UInt32 dirty);
public:
plAxisAnimModifier();
virtual ~plAxisAnimModifier();
CLASSNAME_REGISTER( plAxisAnimModifier );
GETINTERFACE_ANY( plAxisAnimModifier, plSingleModifier );
virtual hsBool MsgReceive(plMessage* msg);
virtual void SetTarget(plSceneObject* so);
void SetAllOrNothing(hsBool b) { fAllOrNothing = b; }
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
void SetXAnim(plKey c) { fXAnim = c; }
void SetYAnim(plKey c) { fYAnim = c; }
void SetNotificationKey(plKey k) { fNotificationKey = k; }
plNotifyMsg* GetNotify() { return fNotify; }
const char* GetAnimLabel() const {return fAnimLabel.c_str();}
void SetAnimLabel(const char* a) {fAnimLabel = a; }
};
#endif // plAxisAnimMod_inc

View File

@ -0,0 +1,118 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "plCloneSpawnModifier.h"
#include "hsResMgr.h"
#include "../plResMgr/plResManager.h"
#include "../plResMgr/plKeyFinder.h"
#include "../pnSceneObject/plSceneObject.h"
#include "../plScene/plSceneNode.h"
#include "../pnMessage/plClientMsg.h"
#include "plgDispatch.h"
#include "../pnMessage/plWarpMsg.h"
#include "../pnMessage/plNodeRefMsg.h"
plCloneSpawnModifier::plCloneSpawnModifier() : fTemplateName(nil), fExportTime(false)
{
}
plCloneSpawnModifier::~plCloneSpawnModifier()
{
delete [] fTemplateName;
}
void plCloneSpawnModifier::Read(hsStream *s, hsResMgr *mgr)
{
delete [] fTemplateName;
fTemplateName = s->ReadSafeString();
plSingleModifier::Read(s, mgr);
}
void plCloneSpawnModifier::Write(hsStream *s, hsResMgr *mgr)
{
s->WriteSafeString(fTemplateName);
plSingleModifier::Write(s, mgr);
}
void plCloneSpawnModifier::SetTemplateName(const char *templateName)
{
delete [] fTemplateName;
fTemplateName = hsStrcpy(templateName);
}
void plCloneSpawnModifier::SetTarget(plSceneObject* so)
{
fTarget = so;
// Spawning the clone here since at Read time fTarget isn't set. Kind of a hack though.
if (fTarget && !fExportTime)
{
// Assume the clone template is in the same age we are
const plLocation& loc = GetKey()->GetUoid().GetLocation();
char ageName[256];
((plResManager*)hsgResMgr::ResMgr())->GetLocationStrings(loc, ageName, nil);
// Spawn the clone
plKey cloneKey = SpawnClone(fTemplateName, ageName, GetTarget()->GetLocalToWorld(), GetKey());
}
}
#include "../plMessage/plLoadCloneMsg.h"
plKey plCloneSpawnModifier::SpawnClone(const char* cloneName, const char* cloneAge, const hsMatrix44& pos, plKey requestor)
{
plResManager* resMgr = (plResManager*)hsgResMgr::ResMgr();
// Find the clone room for this age
const plLocation& loc = plKeyFinder::Instance().FindLocation(cloneAge, "BuiltIn");
// Find the clone template key
plUoid objUoid(loc, plSceneObject::Index(), cloneName);
plKey key = resMgr->FindKey(objUoid);
if (key)
{
plLoadCloneMsg* cloneMsg = TRACKED_NEW plLoadCloneMsg(objUoid, requestor, 0);
cloneMsg->SetBCastFlag(plMessage::kMsgWatch);
plKey cloneKey = cloneMsg->GetCloneKey();//resMgr->CloneKey(key);
cloneMsg->Send();
// Put the clone into the clone room, which also forces it to load.
plKey cloneNodeKey = resMgr->FindKey(kNetClientCloneRoom_KEY);
plNodeRefMsg* nodeRefCloneMsg = TRACKED_NEW plNodeRefMsg(cloneNodeKey, plNodeRefMsg::kOnRequest, -1, plNodeRefMsg::kObject);
resMgr->AddViaNotify(cloneKey, nodeRefCloneMsg, plRefFlags::kActiveRef);
// Warp it into position
plWarpMsg *warpMsg = TRACKED_NEW plWarpMsg;
warpMsg->AddReceiver(cloneKey);
warpMsg->SetTransform(pos);
plgDispatch::MsgSend(warpMsg);
return cloneKey;
}
return nil;
}

View File

@ -0,0 +1,61 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plCloneSpawnModifier_inc
#define plCloneSpawnModifier_inc
#include "../pnModifier/plSingleModifier.h"
class plCloneSpawnModifier : public plSingleModifier
{
protected:
char* fTemplateName;
bool fExportTime;
virtual hsBool IEval(double secs, hsScalar del, UInt32 dirty) { return true; }
public:
plCloneSpawnModifier();
~plCloneSpawnModifier();
CLASSNAME_REGISTER(plCloneSpawnModifier);
GETINTERFACE_ANY(plCloneSpawnModifier, plSingleModifier);
virtual void Read(hsStream *s, hsResMgr *mgr);
virtual void Write(hsStream *s, hsResMgr *mgr);
virtual void SetTarget(plSceneObject* so);
void SetTemplateName(const char *templateName);
// Set this to true at export time so the clone mod won't try to make a
// clone when it's attached
void SetExportTime() { fExportTime = true; }
// Console backdoor
static plKey SpawnClone(const char* cloneName, const char* cloneAge, const hsMatrix44& pos, plKey requestor);
};
#endif // plCloneSpawnModifier_inc

View File

@ -0,0 +1,100 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "hsTypes.h"
#include "plDecalEnableMod.h"
#include "../plMessage/plDynaDecalEnableMsg.h"
#include "../plMessage/plCollideMsg.h"
#include "../pnSceneObject/plSceneObject.h"
#include "../plAvatar/plArmatureMod.h"
#include "hsTimer.h"
#include "hsStream.h"
#include "hsResMgr.h"
plDecalEnableMod::plDecalEnableMod()
{
}
plDecalEnableMod::~plDecalEnableMod()
{
}
hsBool plDecalEnableMod::MsgReceive(plMessage* msg)
{
plCollideMsg* coll = plCollideMsg::ConvertNoRef(msg);
if( coll )
{
plSceneObject* obj = plSceneObject::ConvertNoRef(coll->fOtherKey->ObjectIsLoaded());
if( !obj )
return true;
const plArmatureMod* arm = (const plArmatureMod*)obj->GetModifierByType(plArmatureMod::Index());
if( !arm )
return true;
plKey armKey = arm->GetKey();
int i;
for( i = 0; i < fDecalMgrs.GetCount(); i++ )
{
plDynaDecalEnableMsg* ena = TRACKED_NEW plDynaDecalEnableMsg(fDecalMgrs[i], armKey, hsTimer::GetSysSeconds(), fWetLength, !coll->fEntering);
ena->Send();
}
return true;
}
return plSingleModifier::MsgReceive(msg);
}
void plDecalEnableMod::Read(hsStream* stream, hsResMgr* mgr)
{
plSingleModifier::Read(stream, mgr);
int n = stream->ReadSwap32();
fDecalMgrs.SetCount(n);
int i;
for( i = 0; i < n; i++ )
fDecalMgrs[i] = mgr->ReadKey(stream);
fWetLength = stream->ReadSwapScalar();
}
void plDecalEnableMod::Write(hsStream* stream, hsResMgr* mgr)
{
plSingleModifier::Write(stream, mgr);
stream->WriteSwap32(fDecalMgrs.GetCount());
int i;
for( i = 0; i < fDecalMgrs.GetCount(); i++ )
mgr->WriteKey(stream, fDecalMgrs[i]);
stream->WriteSwapScalar(fWetLength);
}

View File

@ -0,0 +1,64 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plDecalEnableMod_inc
#define plDecalEnableMod_inc
#include "hsTemplates.h"
#include "../pnModifier/plSingleModifier.h"
#include "../pnKeyedObject/plKey.h"
class plDecalEnableMod : public plSingleModifier
{
protected:
hsTArray<plKey> fDecalMgrs;
hsScalar fWetLength;
virtual hsBool IEval(double secs, hsScalar del, UInt32 dirty) { return false; }
public:
plDecalEnableMod();
virtual ~plDecalEnableMod();
CLASSNAME_REGISTER( plDecalEnableMod );
GETINTERFACE_ANY( plDecalEnableMod, plSingleModifier );
virtual hsBool MsgReceive(plMessage* msg);
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
void SetWetLength(hsScalar t) { fWetLength = t; }
hsScalar GetWetLength() const { return fWetLength; }
void AddDecalKey(const plKey& k) { fDecalMgrs.Append(k); }
UInt32 GetNumDecalKeys() const { return fDecalMgrs.GetCount(); }
const plKey& GetDecalKey(int i) const { return fDecalMgrs[i]; }
};
#endif // plDecalEnableMod_inc

View File

@ -0,0 +1,78 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "plDetectorLog.h"
#include "../plStatusLog/plStatusLog.h"
// Don't bother logging detectors in the external release, since it isn't written to disk
#ifdef PLASMA_EXTERNAL_RELEASE
void DetectorLog(const char* format, ...) {}
void DetectorLogSpecial(const char* format, ...) {}
void DetectorLogRed(const char* format, ...) {}
#else
static plStatusLog* gLog =
plStatusLogMgr::GetInstance().CreateStatusLog(
20,
"Detector",
plStatusLog::kFilledBackground | plStatusLog::kDeleteForMe |
plStatusLog::kDontWriteFile | plStatusLog::kAlignToTop);
void DetectorDoLogfile()
{
delete gLog;
gLog = plStatusLogMgr::GetInstance().CreateStatusLog(20,"Detector.log",plStatusLog::kFilledBackground|plStatusLog::kDeleteForMe|plStatusLog::kAlignToTop);
}
void DetectorLog(const char* format, ...)
{
va_list args;
va_start(args, format);
gLog->AddLineV(format, args);
va_end(args);
}
void DetectorLogSpecial(const char* format, ...)
{
va_list args;
va_start(args, format);
gLog->AddLineV(plStatusLog::kGreen, format, args);
va_end(args);
}
void DetectorLogRed(const char* format, ...)
{
va_list args;
va_start(args, format);
gLog->AddLineV(plStatusLog::kRed, format, args);
va_end(args);
}
#endif // PLASMA_EXTERNAL_RELEASE

View File

@ -0,0 +1,34 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plDetectorLog_h_inc
#define plDetectorLog_h_inc
void DetectorLog(const char* format, ...);
void DetectorLogSpecial(const char* format, ...);
void DetectorLogRed(const char* format, ...);
void DetectorDoLogfile();
#endif // plDetectorLog_h_inc

View File

@ -0,0 +1,387 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "plExcludeRegionModifier.h"
#include "../plMessage/plExcludeRegionMsg.h"
#include "hsTemplates.h"
#include "hsResMgr.h"
#include "../pnSceneObject/plCoordinateInterface.h"
#include "plDetectorLog.h"
// For MsgReceive
#include "../plMessage/plCollideMsg.h"
#include "../pnSceneObject/plSceneObject.h"
// For IClear and IRelease
#include "../pnMessage/plWarpMsg.h"
#include "../plMessage/plAvatarMsg.h"
#include "plPhysical.h"
#include "../plPhysical/plSimDefs.h"
#include "../plAvatar/plAvCallbackAction.h"
#include "../plAvatar/plAvBrainGeneric.h"
#include "../plSDL/plSDL.h"
#include "../pnMessage/plSDLModifierMsg.h"
//for hack
#include "../plPhysX/plPXPhysical.h"
#include "../plPhysX/plPXPhysicalControllerCore.h"
#include "NxCapsule.h"
static plPhysical* GetPhysical(plSceneObject* obj)
{
if (obj)
{
const plSimulationInterface* si = obj->GetSimulationInterface();
if (si)
return si->GetPhysical();
}
return nil;
}
plExcludeRegionModifier::plExcludeRegionModifier() :
fSDLModifier(nil),
fSeek(false),
fSeekTime(10.0f)
{
}
plExcludeRegionModifier::~plExcludeRegionModifier()
{
}
void plExcludeRegionModifier::Read(hsStream* stream, hsResMgr* mgr)
{
plSingleModifier::Read(stream, mgr);
int numPoints = stream->ReadSwap32();
for (int i = 0; i < numPoints; i++)
{
fSafePoints.push_back(mgr->ReadKey(stream));
}
fSeek = stream->ReadBool();
fSeekTime = stream->ReadSwapScalar();
}
void plExcludeRegionModifier::Write(hsStream* stream, hsResMgr* mgr)
{
plSingleModifier::Write(stream, mgr);
int numPoints = fSafePoints.size();
stream->WriteSwap32(numPoints);
for (int i = 0; i < numPoints; i++)
{
mgr->WriteKey(stream,fSafePoints[i]);
}
stream->WriteBool(fSeek);
stream->WriteSwapScalar(fSeekTime);
}
void plExcludeRegionModifier::ISetPhysicalState(bool cleared)
{
plPhysical* phys = GetPhysical(GetTarget());
if (phys)
{
phys->ExcludeRegionHack(cleared);
if (cleared)
{
phys->AddLOSDB(plSimDefs::kLOSDBUIBlockers);
if (HasFlag(kBlockCameras))
phys->AddLOSDB(plSimDefs::kLOSDBCameraBlockers);
}
else
{
phys->RemoveLOSDB(plSimDefs::kLOSDBUIBlockers);
if (HasFlag(kBlockCameras))
phys->RemoveLOSDB(plSimDefs::kLOSDBCameraBlockers);
}
}
}
hsBool plExcludeRegionModifier::MsgReceive(plMessage* msg)
{
plExcludeRegionMsg *exclMsg = plExcludeRegionMsg::ConvertNoRef(msg);
if (exclMsg)
{
if (exclMsg->GetCmd() == plExcludeRegionMsg::kClear)
{
DetectorLogSpecial("Clearing exclude region %s", GetKeyName());
IMoveAvatars();
fContainedAvatars.Reset();
ISetPhysicalState(true);
}
else if (exclMsg->GetCmd() == plExcludeRegionMsg::kRelease)
{
DetectorLogSpecial("Releasing exclude region %s", GetKeyName());
ISetPhysicalState(false);
}
GetTarget()->DirtySynchState(kSDLXRegion, exclMsg->fSynchFlags);
return true;
}
// Avatar entering or exiting our volume. Only the owner of the SO logs this since
// it does all the moving at clear time.
plCollideMsg *collideMsg = plCollideMsg::ConvertNoRef(msg);
if (collideMsg)
{
if (collideMsg->fEntering)
{
//DetectorLogSpecial("Avatar enter exclude region %s",GetKeyName());
fContainedAvatars.Append(collideMsg->fOtherKey);
}
else
{
//DetectorLogSpecial("Avatar exit exclude region %s",GetKeyName());
int idx = fContainedAvatars.Find(collideMsg->fOtherKey);
if (idx != fContainedAvatars.kMissingIndex)
fContainedAvatars.Remove(idx);
}
return true;
}
return plSingleModifier::MsgReceive(msg);
}
void plExcludeRegionModifier::AddTarget(plSceneObject* so)
{
if (so)
{
delete fSDLModifier;
fSDLModifier = TRACKED_NEW plExcludeRegionSDLModifier(this);
so->AddModifier(fSDLModifier);
}
plSingleModifier::SetTarget(so);
}
void plExcludeRegionModifier::RemoveTarget( plSceneObject *so )
{
if (so && fSDLModifier)
{
so->RemoveModifier(fSDLModifier);
delete fSDLModifier;
fSDLModifier = nil;
}
plSingleModifier::RemoveTarget(so);
}
void plExcludeRegionModifier::AddSafePoint(plKey& key)
{
fSafePoints.push_back(key);
}
int plExcludeRegionModifier::IFindClosestSafePoint(plKey avatar)
{
float closestDist = 0.f;
int closestIdx = -1;
plSceneObject* avObj = plSceneObject::ConvertNoRef(avatar->GetObjectPtr());
if (!avObj)
return -1;
hsVector3 avPos;
avObj->GetCoordinateInterface()->GetLocalToWorld().GetTranslate(&avPos);
for (int i = 0; i < fSafePoints.size(); i++)
{
plSceneObject* safeObj = plSceneObject::ConvertNoRef(fSafePoints[i]->GetObjectPtr());
hsVector3 safePos;
safeObj->GetCoordinateInterface()->GetLocalToWorld().GetTranslate(&safePos);
float dist = (safePos - avPos).Magnitude();
if (dist < closestDist || closestIdx == -1)
{
closestDist = dist;
closestIdx = i;
}
}
return closestIdx;
}
// check to make sure that the avatar and the exclude region are in the same subworld
bool plExcludeRegionModifier::ICheckSubworlds(plKey avatar)
{
plSceneObject* avObj = plSceneObject::ConvertNoRef(avatar->GetObjectPtr());
if (avObj)
{
// get the avatar modifier
const plArmatureMod *avMod = (plArmatureMod*)avObj->GetModifierByType(plArmatureMod::Index());
if (avMod)
{
// get the avatar controller
plPhysicalControllerCore* avController = avMod->GetController();
if (avController)
{
// get physical of the detector region
plPhysical* phys = GetPhysical(GetTarget());
if (phys)
{
// are they in the same subworld?
if ( phys->GetWorldKey() == avController->GetSubworld() )
return true;
else
return false;
}
}
}
}
return false;
}
// Move avatars out of volume
void plExcludeRegionModifier::IMoveAvatars()
{
//some reason this is not always finding all avatars might have something to do with
//Physx trigger flutter. Adding in brute force method
/*
for (int i = 0; i < fContainedAvatars.Count(); i++)
{
if ( ICheckSubworlds(fContainedAvatars[i]) )
{
int closestIdx = IFindClosestSafePoint(fContainedAvatars[i]);
if (closestIdx != -1)
{
plAvSeekMsg* msg = TRACKED_NEW plAvSeekMsg;
msg->SetBCastFlag(plMessage::kPropagateToModifiers);
msg->AddReceiver(fContainedAvatars[i]);
msg->fSmartSeek = fSeek;
msg->fDuration = fSeekTime;
msg->fSeekPoint = fSafePoints[closestIdx];
msg->fFlags |= plAvSeekMsg::kSeekFlagUnForce3rdPersonOnFinish;
msg->Send();
}
}
}
*/
plPXPhysical* phys =(plPXPhysical*) GetPhysical(GetTarget());
if (phys)
{
plKey DetectorWorldKey = phys->GetWorldKey();
int numControllers = plPXPhysicalControllerCore::GetNumberOfControllersInThisSubWorld(phys->GetWorldKey());
if (numControllers > 0)
{
plPXPhysicalControllerCore** controllers = TRACKED_NEW plPXPhysicalControllerCore*[numControllers];
int actualCount = plPXPhysicalControllerCore::GetControllersInThisSubWorld(phys->GetWorldKey(), numControllers, controllers);
for (int i=0;i<actualCount;i++)
{
NxCapsule cap;
controllers[i]->GetWorldSpaceCapsule(cap);
if(phys->OverlapWithCapsule(cap))
{
plSceneObject* so = plSceneObject::ConvertNoRef(controllers[i]->GetOwner()->ObjectIsLoaded());
const plArmatureMod* constAvMod = (plArmatureMod*)so->GetModifierByType(plArmatureMod::Index());
if(constAvMod)
{
plAvBrainGeneric *curGenBrain = (plAvBrainGeneric *)constAvMod->FindBrainByClass(plAvBrainGeneric::Index());
// *** warning; if there's more than one generic brain active, this will only look at the first
if (curGenBrain && curGenBrain->GetType() == plAvBrainGeneric::kLadder)
{
plAvBrainGenericMsg* pMsg = TRACKED_NEW plAvBrainGenericMsg(
nil,
constAvMod->GetKey(),
plAvBrainGenericMsg::kGotoStage,
-1,
false,
0.0,
false,
false,
0.0
);
pMsg->Send();
}
else
{
int closestIdx = IFindClosestSafePoint(controllers[i]->GetOwner());
if (closestIdx != -1)
{
plAvSeekMsg* msg = TRACKED_NEW plAvSeekMsg;
msg->SetBCastFlag(plMessage::kPropagateToModifiers);
msg->AddReceiver(controllers[i]->GetOwner());
msg->fSmartSeek = fSeek;
msg->fDuration = fSeekTime;
msg->fSeekPoint = fSafePoints[closestIdx];
msg->fFlags |= plAvSeekMsg::kSeekFlagUnForce3rdPersonOnFinish;
msg->Send();
}
}
}
}
}
delete[] controllers;
}
}
}
///////////////////////////////////////////////////////////////////////////////
plExcludeRegionSDLModifier::plExcludeRegionSDLModifier() : fXRegion(nil)
{
}
plExcludeRegionSDLModifier::plExcludeRegionSDLModifier(plExcludeRegionModifier* xregion) :
fXRegion(xregion)
{
}
static const char* kXRegionSDLCleared = "cleared";
void plExcludeRegionSDLModifier::IPutCurrentStateIn(plStateDataRecord* dstState)
{
plSimpleStateVariable* var = dstState->FindVar(kXRegionSDLCleared);
if (var)
{
plPhysical* phys = GetPhysical(GetTarget());
if (phys)
{
//bool cleared = phys->GetGroup() == plSimDefs::kGroupStatic;
bool cleared = phys->GetGroup() == plSimDefs::kGroupExcludeRegion;
var->Set(cleared);
}
}
}
void plExcludeRegionSDLModifier::ISetCurrentStateFrom(const plStateDataRecord* srcState)
{
plSimpleStateVariable* var = srcState->FindVar(kXRegionSDLCleared);
if (var)
{
bool cleared;
var->Get(&cleared);
DetectorLogSpecial("SDL %s exclude region %s", cleared ? "clearing" : "releasing", fXRegion->GetKeyName());
fXRegion->ISetPhysicalState(cleared);
}
}

View File

@ -0,0 +1,100 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plExcludeRegionModifier_inc
#define plExcludeRegionModifier_inc
#include "../pnModifier/plSingleModifier.h"
#include "hsMatrix44.h"
#include "hsTemplates.h"
#include "../plModifier/plSDLModifier.h"
//
// Moves all of the avatars out of the area it's SceneObject occupies and makes it
// physical on clear message. Makes the SO non-physical again on release message.
//
class plExcludeRegionSDLModifier;
class plExcludeRegionModifier : public plSingleModifier
{
protected:
enum
{
kBlockCameras,
};
std::vector<plKey> fSafePoints; // Safe positions to move avatars to
hsTArray<plKey> fContainedAvatars; // Avatars inside our volume
plExcludeRegionSDLModifier *fSDLModifier;
hsBool fSeek; // use smart seek or teleport?
hsScalar fSeekTime; // how long to seek for
virtual hsBool IEval(double secs, hsScalar del, UInt32 dirty) { return true; }
void ISetPhysicalState(bool cleared);
int IFindClosestSafePoint(plKey avatar);
bool ICheckSubworlds(plKey avatar);
void IMoveAvatars();
friend class plExcludeRegionSDLModifier;
public:
plExcludeRegionModifier();
~plExcludeRegionModifier();
CLASSNAME_REGISTER(plExcludeRegionModifier);
GETINTERFACE_ANY(plExcludeRegionModifier, plSingleModifier);
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
virtual hsBool MsgReceive(plMessage* msg);
virtual void AddTarget(plSceneObject* so);
virtual void RemoveTarget( plSceneObject *so );
void AddSafePoint(plKey& key);
void UseSmartSeek() { fSeek = true; }
void SetSeekTime(hsScalar s) { fSeekTime = s; }
void SetBlockCameras(bool block) { fFlags.SetBit(kBlockCameras, block); }
};
class plExcludeRegionSDLModifier : public plSDLModifier
{
protected:
plExcludeRegionModifier* fXRegion;
void IPutCurrentStateIn(plStateDataRecord* dstState);
void ISetCurrentStateFrom(const plStateDataRecord* srcState);
public:
plExcludeRegionSDLModifier();
plExcludeRegionSDLModifier(plExcludeRegionModifier* xregion);
CLASSNAME_REGISTER(plExcludeRegionSDLModifier);
GETINTERFACE_ANY(plExcludeRegionSDLModifier, plSDLModifier);
const char* GetSDLName() const { return kSDLXRegion; }
};
#endif // plExcludeRegionModifier_inc

View File

@ -0,0 +1,86 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "plGameMarkerModifier.h"
#include "../plMessage/plCollideMsg.h"
#include "../pnMessage/plNotifyMsg.h"
#include "../pnSceneObject/plSceneObject.h"
hsBool plGameMarkerModifier::MsgReceive(plMessage* msg)
{
plCollideMsg *collideMsg = plCollideMsg::ConvertNoRef(msg);
if (collideMsg)
{
if (collideMsg->fEntering)
{
plNotifyMsg* notify = TRACKED_NEW plNotifyMsg;
notify->AddCollisionEvent(true, collideMsg->fOtherKey, GetTarget()->GetKey());
notify->Send(hsgResMgr::ResMgr()->FindKey(kMarkerMgr_KEY));
}
}
return plSingleModifier::MsgReceive(msg);
}
plKey plGameMarkerModifier::IFindCloneKey(plKey baseKey)
{
const plUoid& myUoid = GetKey()->GetUoid();
plUoid cloneUoid = baseKey->GetUoid();
cloneUoid.SetClone(myUoid.GetClonePlayerID(), myUoid.GetCloneID());
return hsgResMgr::ResMgr()->FindKey(cloneUoid);
}
void plGameMarkerModifier::FixupAnimKeys()
{
fGreenAnimKey = IFindCloneKey(fGreenAnimKey);
fRedAnimKey = IFindCloneKey(fRedAnimKey);
fOpenAnimKey = IFindCloneKey(fOpenAnimKey);
fBounceAnimKey = IFindCloneKey(fBounceAnimKey);
}
void plGameMarkerModifier::Read(hsStream* stream, hsResMgr* mgr)
{
plSingleModifier::Read(stream, mgr);
fGreenAnimKey = mgr->ReadKey(stream);
fRedAnimKey = mgr->ReadKey(stream);
fOpenAnimKey = mgr->ReadKey(stream);
fBounceAnimKey = mgr->ReadKey(stream);
fPlaceSndIdx = stream->ReadSwap16();
fHitSndIdx = stream->ReadSwap16();
}
void plGameMarkerModifier::Write(hsStream* stream, hsResMgr* mgr)
{
plSingleModifier::Write(stream, mgr);
mgr->WriteKey(stream, fGreenAnimKey);
mgr->WriteKey(stream, fRedAnimKey);
mgr->WriteKey(stream, fOpenAnimKey);
mgr->WriteKey(stream, fBounceAnimKey);
stream->WriteSwap16(fPlaceSndIdx);
stream->WriteSwap16(fHitSndIdx);
}

View File

@ -0,0 +1,73 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plGameMarkerModifier_h_inc
#define plGameMarkerModifier_h_inc
#include "../pnModifier/plSingleModifier.h"
class plGameMarkerModifier : public plSingleModifier
{
protected:
plKey fGreenAnimKey;
plKey fRedAnimKey;
plKey fOpenAnimKey;
plKey fBounceAnimKey;
UInt16 fPlaceSndIdx;
UInt16 fHitSndIdx;
virtual hsBool IEval(double secs, hsScalar del, UInt32 dirty) { return true; }
plKey IFindCloneKey(plKey baseKey);
friend class pfMarkerInfo;
friend class pfMarkerInfoOwned;
public:
plGameMarkerModifier() {}
CLASSNAME_REGISTER(plGameMarkerModifier);
GETINTERFACE_ANY(plGameMarkerModifier, plSingleModifier);
void ExportInit(plKey greenKey, plKey redKey, plKey openKey, plKey bounceAnimKey,
UInt16 placeSndIdx, UInt16 hitSndIdx)
{
fGreenAnimKey = greenKey;
fRedAnimKey = redKey;
fOpenAnimKey = openKey;
fBounceAnimKey = bounceAnimKey;
fPlaceSndIdx = placeSndIdx;
fHitSndIdx = hitSndIdx;
}
void FixupAnimKeys();
virtual hsBool MsgReceive(plMessage* msg);
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
};
#endif // plGameMarkerModifier_h_inc

View File

@ -0,0 +1,86 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "hsTypes.h"
#include "plImageLibMod.h"
#include "../plGImage/plBitmap.h"
#include "../pnMessage/plRefMsg.h"
#include "hsTimer.h"
#include "hsStream.h"
#include "hsResMgr.h"
plImageLibMod::plImageLibMod()
{
}
plImageLibMod::~plImageLibMod()
{
}
hsBool plImageLibMod::MsgReceive(plMessage* msg)
{
plGenRefMsg *refMsg = plGenRefMsg::ConvertNoRef( msg );
if( refMsg != nil )
{
if( refMsg->GetContext() & ( plRefMsg::kOnCreate | plRefMsg::kOnRequest | plRefMsg::kOnReplace ) )
{
if( fImages.GetCount() <= refMsg->fWhich )
fImages.ExpandAndZero( refMsg->fWhich + 1 );
fImages[ refMsg->fWhich ] = plBitmap::ConvertNoRef( refMsg->GetRef() );
}
else if( refMsg->GetContext() & ( plRefMsg::kOnRemove | plRefMsg::kOnDestroy ) )
{
fImages[ refMsg->fWhich ] = nil;
}
return true;
}
return plSingleModifier::MsgReceive(msg);
}
void plImageLibMod::Read(hsStream* stream, hsResMgr* mgr)
{
plSingleModifier::Read(stream, mgr);
UInt32 i, count = stream->ReadSwap32();
fImages.SetCountAndZero( count );
for( i = 0; i < count; i++ )
mgr->ReadKeyNotifyMe( stream, TRACKED_NEW plGenRefMsg( GetKey(), plRefMsg::kOnCreate, i, kRefImage ), plRefFlags::kActiveRef );
}
void plImageLibMod::Write(hsStream* stream, hsResMgr* mgr)
{
plSingleModifier::Write(stream, mgr);
stream->WriteSwap32( fImages.GetCount() );
UInt32 i;
for( i = 0; i < fImages.GetCount(); i++ )
mgr->WriteKey( stream, fImages[ i ]->GetKey() );
}

View File

@ -0,0 +1,63 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plImageLibMod_inc
#define plImageLibMod_inc
#include "hsTemplates.h"
#include "../pnModifier/plSingleModifier.h"
#include "../pnKeyedObject/plKey.h"
class plBitmap;
class plImageLibMod : public plSingleModifier
{
protected:
hsTArray<plBitmap *> fImages;
virtual hsBool IEval(double secs, hsScalar del, UInt32 dirty) { return false; }
public:
plImageLibMod();
virtual ~plImageLibMod();
CLASSNAME_REGISTER( plImageLibMod );
GETINTERFACE_ANY( plImageLibMod, plSingleModifier );
virtual hsBool MsgReceive(plMessage* msg);
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
enum Refs
{
kRefImage = 0
};
UInt32 GetNumImages( void ) const { return fImages.GetCount(); }
};
#endif // plImageLibMod_inc

View File

@ -0,0 +1,56 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "hsTypes.h"
#include "plInterfaceInfoModifier.h"
#include "hsResMgr.h"
#include "../pnKeyedObject/plKey.h"
plInterfaceInfoModifier::plInterfaceInfoModifier()
{
}
plInterfaceInfoModifier::~plInterfaceInfoModifier()
{
fKeyList.Reset();
}
void plInterfaceInfoModifier::Read(hsStream* s, hsResMgr* mgr)
{
plSingleModifier::Read(s, mgr);
int i = s->ReadSwap32();
for (int x = 0; x < i; x++)
fKeyList.Append(mgr->ReadKey(s));
}
void plInterfaceInfoModifier::Write(hsStream* s, hsResMgr* mgr)
{
plSingleModifier::Write(s, mgr);
s->WriteSwap32(fKeyList.Count());
for (int i = 0; i < fKeyList.Count(); i++)
mgr->WriteKey(s, fKeyList[i]);
}

View File

@ -0,0 +1,56 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plInterfaceInfoMod_inc
#define plInterfaceInfoMod_inc
#include "../pnModifier/plSingleModifier.h"
#include "../pnKeyedObject/plKey.h"
#include "hsTemplates.h"
class plInterfaceInfoModifier : public plSingleModifier
{
protected:
hsTArray<plKey> fKeyList;
virtual hsBool IEval(double secs, hsScalar del, UInt32 dirty){ return true; }
public:
plInterfaceInfoModifier();
~plInterfaceInfoModifier();
CLASSNAME_REGISTER( plInterfaceInfoModifier );
GETINTERFACE_ANY( plInterfaceInfoModifier, plSingleModifier );
void AddRefdKey(plKey &k) { fKeyList.Append(k); }
int GetNumReferencedKeys() const { return fKeyList.Count(); }
plKey GetReferencedKey(int i) const { return fKeyList[i]; }
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
};
#endif // plInterfaceInfoMod_inc

View File

@ -0,0 +1,189 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "hsMatrix44.h"
#include "plLayerSDLModifier.h"
#include "../plSDL/plSDL.h"
#include "../plSurface/plLayerAnimation.h"
// static vars
char plLayerSDLModifier::kStrAtc[]="atc";
char plLayerSDLModifier::kStrPassThruChannels[]="passThruChannels";
char plLayerSDLModifier::kStrTransform[]="transform";
char plLayerSDLModifier::kStrChannelData[]="channelData";
//char plLayerSDLModifier::kStrPreShadeColor[]="preshadeColor";
//char plLayerSDLModifier::kStrRuntimeColor[]="runtimeColor";
//char plLayerSDLModifier::kStrAmbientColor[]="ambientColor";
//char plLayerSDLModifier::kStrOpacity[]="opacity";
plKey plLayerSDLModifier::GetStateOwnerKey() const
{
return fLayerAnimation ? fLayerAnimation->GetKey() : nil;
}
//
// Copy atc from current state into sdl
//
void plLayerSDLModifier::IPutCurrentStateIn(plStateDataRecord* dstState)
{
plLayerAnimation* layer=GetLayerAnimation();
hsAssert(layer, "nil layer animation");
plSDStateVariable* atcVar = dstState->FindSDVar(kStrAtc);
plStateDataRecord* atcStateDataRec = atcVar->GetStateDataRecord(0);
IPutATC(atcStateDataRec, &layer->GetTimeConvert());
int passThru=layer->fPassThruChannels;
dstState->FindVar(kStrPassThruChannels)->Set(passThru);
int transformSize = 0;
if (layer->fTransform && (layer->fOwnedChannels & plLayerInterface::kTransform))
transformSize = 16;
plSimpleStateVariable *transformVar = dstState->FindVar(kStrTransform);
if (transformVar->GetCount() != transformSize)
transformVar->Alloc(transformSize);
if (transformSize > 0)
{
int i,j;
for(i=0;i<4;i++)
{
for(j=0;j<4;j++)
{
float f=layer->fTransform->fMap[i][j];
transformVar->Set(&f, i*4+j);
}
}
}
int channelDataSize = 0;
if (layer->fPreshadeColor && (layer->fOwnedChannels & plLayerInterface::kPreshadeColor))
channelDataSize += 3;
if (layer->fRuntimeColor && (layer->fOwnedChannels & plLayerInterface::kRuntimeColor))
channelDataSize += 3;
if (layer->fAmbientColor && (layer->fOwnedChannels & plLayerInterface::kAmbientColor))
channelDataSize += 3;
if (layer->fOpacity && (layer->fOwnedChannels & plLayerInterface::kOpacity))
channelDataSize += 1;
plSimpleStateVariable *channelVar = dstState->FindVar(kStrChannelData);
if (channelVar->GetCount() != channelDataSize)
channelVar->Alloc(channelDataSize);
int channelIdx = 0;
if (layer->fPreshadeColor && (layer->fOwnedChannels & plLayerInterface::kPreshadeColor))
{
channelVar->Set((UInt8)(layer->fPreshadeColor->r * 255), channelIdx++);
channelVar->Set((UInt8)(layer->fPreshadeColor->g * 255), channelIdx++);
channelVar->Set((UInt8)(layer->fPreshadeColor->b * 255), channelIdx++);
}
if (layer->fRuntimeColor && (layer->fOwnedChannels & plLayerInterface::kRuntimeColor))
{
channelVar->Set((UInt8)(layer->fRuntimeColor->r * 255), channelIdx++);
channelVar->Set((UInt8)(layer->fRuntimeColor->g * 255), channelIdx++);
channelVar->Set((UInt8)(layer->fRuntimeColor->b * 255), channelIdx++);
}
if (layer->fAmbientColor && (layer->fOwnedChannels & plLayerInterface::kAmbientColor))
{
channelVar->Set((UInt8)(layer->fAmbientColor->r * 255), channelIdx++);
channelVar->Set((UInt8)(layer->fAmbientColor->g * 255), channelIdx++);
channelVar->Set((UInt8)(layer->fAmbientColor->b * 255), channelIdx++);
}
if (layer->fOpacity && (layer->fOwnedChannels & plLayerInterface::kOpacity))
channelVar->Set((UInt8)(*layer->fOpacity * 255), channelIdx++);
}
//
// Change the object's animation state to reflect what is specified in the
// stateDataRecord.
//
void plLayerSDLModifier::ISetCurrentStateFrom(const plStateDataRecord* srcState)
{
plLayerAnimation* layer=GetLayerAnimation();
hsAssert(layer, "nil layer animation");
plSDStateVariable* atcVar = srcState->FindSDVar(kStrAtc);
plStateDataRecord* atcStateDataRec = atcVar->GetStateDataRecord(0);
ISetCurrentATC(atcStateDataRec, &layer->GetTimeConvert());
int pass;
if (srcState->FindVar(kStrPassThruChannels)->Get(&pass))
layer->fPassThruChannels=pass;
plSimpleStateVariable *transformVar = srcState->FindVar(kStrTransform);
if (transformVar->IsUsed() && transformVar->GetCount() == 16)
{
int i,j;
for(i=0;i<4;i++)
{
for(j=0;j<4;j++)
{
float f;
srcState->FindVar(kStrTransform)->Get(&f, i*4+j);
layer->fTransform->fMap[i][j]=f;
}
}
}
plSimpleStateVariable *channelVar = srcState->FindVar(kStrChannelData);
int channelIdx = 0;
UInt8 val;
if (layer->fPreshadeColor && (layer->fOwnedChannels & plLayerInterface::kPreshadeColor))
{
channelVar->Get(&val, channelIdx++);
layer->fPreshadeColor->r = val / 255.f;
channelVar->Get(&val, channelIdx++);
layer->fPreshadeColor->g = val / 255.f;
channelVar->Get(&val, channelIdx++);
layer->fPreshadeColor->b = val / 255.f;
}
if (layer->fRuntimeColor && (layer->fOwnedChannels & plLayerInterface::kRuntimeColor))
{
channelVar->Get(&val, channelIdx++);
layer->fRuntimeColor->r = val / 255.f;
channelVar->Get(&val, channelIdx++);
layer->fRuntimeColor->g = val / 255.f;
channelVar->Get(&val, channelIdx++);
layer->fRuntimeColor->b = val / 255.f;
}
if (layer->fAmbientColor && (layer->fOwnedChannels & plLayerInterface::kAmbientColor))
{
channelVar->Get(&val, channelIdx++);
layer->fAmbientColor->r = val / 255.f;
channelVar->Get(&val, channelIdx++);
layer->fAmbientColor->g = val / 255.f;
channelVar->Get(&val, channelIdx++);
layer->fAmbientColor->b = val / 255.f;
}
if (layer->fOpacity && (layer->fOwnedChannels & plLayerInterface::kOpacity))
{
channelVar->Get(&val, channelIdx++);
*layer->fOpacity = val / 255.f;
}
layer->fCurrentTime = -1.f; // force an eval
}

View File

@ -0,0 +1,68 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plLayerSDLModifier_inc
#define plLayerSDLModifier_inc
#include "../plModifier/plAnimTimeConvertSDLModifier.h"
//
// This modifier is responsible for sending and recving
// an layer's animation state (basically an animTimeConvert)
//
class plLayerAnimation;
class plStateDataRecord;
class plLayerSDLModifier : public plAnimTimeConvertSDLModifier
{
protected:
static char kStrAtc[]; // animTimeConvert var name
static char kStrPassThruChannels[];
static char kStrTransform[];
static char kStrChannelData[];
//static char kStrPreShadeColor[];
//static char kStrRuntimeColor[];
//static char kStrAmbientColor[];
//static char kStrOpacity[];
plLayerAnimation* fLayerAnimation;
void IPutCurrentStateIn(plStateDataRecord* dstState);
void ISetCurrentStateFrom(const plStateDataRecord* srcState);
public:
CLASSNAME_REGISTER( plLayerSDLModifier);
GETINTERFACE_ANY( plLayerSDLModifier, plAnimTimeConvertSDLModifier);
plLayerSDLModifier() : fLayerAnimation(nil) {}
const char* GetSDLName() const { return kSDLLayer; }
plLayerAnimation* GetLayerAnimation() const { return fLayerAnimation; }
void SetLayerAnimation(plLayerAnimation* l) { fLayerAnimation=l; AddTarget(nil); }
plKey GetStateOwnerKey() const;
};
#endif // plLayerSDLModifier_inc

View File

@ -0,0 +1,265 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "hsTypes.h"
#include "plLogicModifier.h"
#include "plgDispatch.h"
#include "../pnTimer/plTimerCallbackManager.h"
#include "../pnModifier/plConditionalObject.h"
#include "../plPhysical/plDetectorModifier.h"
#include "../plMessage/plCondRefMsg.h"
#include "../plMessage/plTimerCallbackMsg.h"
#include "../plMessage/plActivatorMsg.h"
#include "../pnNetCommon/plNetApp.h"
#include "../pnSceneObject/plSceneObject.h"
#include "../pnKeyedObject/plKey.h"
#include "../pnMessage/plFakeOutMsg.h"
#include "../pnMessage/plCursorChangeMsg.h"
#include "../pnMessage/plNotifyMsg.h"
#include "../plModifier/plDetectorLog.h"
#include "../plInputCore/plSceneInputInterface.h"
#include "../../FeatureLib/pfConditional/plFacingConditionalObject.h"
#include "../../FeatureLib/pfConditional/plObjectInBoxConditionalObject.h"
plLogicModifier::plLogicModifier()
{
fMyCursor = plCursorChangeMsg::kCursorUp;
}
plLogicModifier::~plLogicModifier()
{
}
// this is a special check that asks conditions
// not if they are satisfied, but if they are ready
// to be satisfied. Used by the activator condition
// to check that any special conditions (like players
// in boxes) are okay or not.
hsBool plLogicModifier::VerifyConditions(plMessage* msg)
{
for (int i = 0; i < fConditionList.Count(); i++)
{
if (!fConditionList[i]->Verify(msg))
return false;
}
return true;
}
hsBool plLogicModifier::MsgReceive(plMessage* msg)
{
hsBool retVal = false;
// read messages:
plCondRefMsg* pCondMsg = plCondRefMsg::ConvertNoRef(msg);
if (pCondMsg)
{
plConditionalObject* pCond = plConditionalObject::ConvertNoRef( pCondMsg->GetRef() );
if (pCond && (pCondMsg->GetContext() & (plRefMsg::kOnCreate|plRefMsg::kOnRequest|plRefMsg::kOnReplace)))
{
if (fConditionList.Count() <= pCondMsg->fWhich)
fConditionList.ExpandAndZero(pCondMsg->fWhich + 1);
fConditionList[pCondMsg->fWhich] = pCond;
pCond->SetLogicMod(this);
if (pCond->HasFlag(plConditionalObject::kLocalElement))
SetFlag(kLocalElement);
}
retVal = true;
}
plTimerCallbackMsg* pTMsg = plTimerCallbackMsg::ConvertNoRef(msg);
if (pTMsg)
{
hsBool netRequest = msg->HasBCastFlag(plMessage::kNetNonLocal);
Trigger(netRequest);
}
plActivatorMsg* pActivateMsg = plActivatorMsg::ConvertNoRef(msg);
if (pActivateMsg)
{
// if (pActivateMsg->fTriggerType == plActivatorMsg::kUnPickedTrigger)
{
// UnTrigger();
// return true;
}
// else
{
hsBool ignore=false;
// Ignore collision activations by remote players
if (pActivateMsg->fTriggerType==plActivatorMsg::kCollideEnter ||
pActivateMsg->fTriggerType==plActivatorMsg::kCollideExit ||
pActivateMsg->fTriggerType==plActivatorMsg::kCollideContact)
{
if (plNetClientApp::GetInstance()->IsRemotePlayerKey(pActivateMsg->fHitterObj))
ignore=true;
}
if (!ignore)
{
for (int i = 0; i < fConditionList.Count(); i++)
{
if (fConditionList[i]->MsgReceive(msg))
return true;
}
}
}
}
plNotifyMsg* pNotify = plNotifyMsg::ConvertNoRef(msg);
if (pNotify)
{
for (int i = 0; i < fConditionList.Count(); i++)
{
if (fConditionList[i]->MsgReceive(msg))
return true;
}
}
plFakeOutMsg* pFakeMsg = plFakeOutMsg::ConvertNoRef(msg);
if (pFakeMsg)
{
plCursorChangeMsg* pMsg = 0;
if ((VerifyConditions(pFakeMsg) && fMyCursor) && !Disabled())
pMsg = TRACKED_NEW plCursorChangeMsg(fMyCursor, 1);
else
{
#ifndef PLASMA_EXTERNAL_RELEASE
// try to determine the reasons for not displaying cursor
if (plSceneInputInterface::fShowLOS)
{
if ( Disabled() )
{
DetectorLogRed("%s: LogicMod is disabled", GetKeyName());
}
else
{
for (int i = 0; i < fConditionList.Count(); i++)
{
if (!fConditionList[i]->Verify(msg))
{
if ( plObjectInBoxConditionalObject::ConvertNoRef(fConditionList[i]) )
DetectorLogRed("%s: LogicMod InRegion conditional not met", fConditionList[i]->GetKeyName());
else if ( plFacingConditionalObject::ConvertNoRef(fConditionList[i]) )
DetectorLogRed("%s: LogicMod Facing conditional not met", fConditionList[i]->GetKeyName());
else
DetectorLogRed("%s: LogicMod <unknown> conditional not met", fConditionList[i]->GetKeyName());
}
}
}
}
#endif // PLASMA_EXTERNAL_RELEASE
pMsg = TRACKED_NEW plCursorChangeMsg(plCursorChangeMsg::kNullCursor, 1);
}
pMsg->AddReceiver( pFakeMsg->GetSender() );
pMsg->SetSender(GetKey());
plgDispatch::MsgSend(pMsg);
return true;
}
return (plLogicModBase::MsgReceive(msg));
}
void plLogicModifier::RequestTrigger(hsBool netRequest)
{
for (int i = 0; i < fConditionList.Count(); i++)
{
if (!fConditionList[i]->Satisfied())
return;
}
plLogicModBase::RequestTrigger(netRequest);
}
void plLogicModifier::PreTrigger(hsBool netRequest)
{
if (!IEvalCounter())
return;
if (fTimer)
{
plgTimerCallbackMgr::NewTimer( fTimer, TRACKED_NEW plTimerCallbackMsg( GetKey() ) );
return;
}
plLogicModBase::PreTrigger(netRequest);
}
void plLogicModifier::Reset(bool bCounterReset)
{
plLogicModBase::Reset(bCounterReset);
for (int i = 0; i < fConditionList.Count(); i++)
fConditionList[i]->Reset();
}
void plLogicModifier::Read(hsStream* stream, hsResMgr* mgr)
{
plLogicModBase::Read(stream, mgr);
plCondRefMsg* refMsg;
int n = stream->ReadSwap32();
fConditionList.SetCountAndZero(n);
int i;
for(i = 0; i < n; i++ )
{
refMsg = TRACKED_NEW plCondRefMsg(GetKey(), i);
mgr->ReadKeyNotifyMe(stream,refMsg, plRefFlags::kActiveRef);
}
fMyCursor = stream->ReadSwap32();
}
void plLogicModifier::Write(hsStream* stream, hsResMgr* mgr)
{
plLogicModBase::Write(stream, mgr);
stream->WriteSwap32(fConditionList.GetCount());
for( int i = 0; i < fConditionList.GetCount(); i++ )
mgr->WriteKey(stream, fConditionList[i]);
stream->WriteSwap32(fMyCursor);
}
void plLogicModifier::AddCondition(plConditionalObject* c)
{
plGenRefMsg *msg= TRACKED_NEW plGenRefMsg(GetKey(), plRefMsg::kOnCreate, -1, -1);
hsgResMgr::ResMgr()->AddViaNotify(c->GetKey(), msg, plRefFlags::kActiveRef);
fConditionList.Append(c);
c->SetLogicMod(this);
if (c->HasFlag(plConditionalObject::kLocalElement))
SetFlag(kLocalElement);
}
void plLogicModifier::VolumeIgnoreExtraEnters(bool ignore /* = true */)
{
for (int curCondition = 0; curCondition < fConditionList.GetCount(); ++curCondition)
{
plVolumeSensorConditionalObject* condition = plVolumeSensorConditionalObject::ConvertNoRef(fConditionList[curCondition]);
if (condition)
condition->IgnoreExtraEnters(ignore);
}
}

View File

@ -0,0 +1,61 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plLogicModifier_inc
#define plLogicModifier_inc
#include "../pnModifier/plLogicModBase.h"
class plLogicModifier : public plLogicModBase
{
protected:
hsTArray<plConditionalObject*> fConditionList;
virtual void PreTrigger(hsBool netRequest);
public:
plLogicModifier();
~plLogicModifier();
CLASSNAME_REGISTER( plLogicModifier );
GETINTERFACE_ANY( plLogicModifier, plLogicModBase );
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
virtual hsBool MsgReceive(plMessage* msg);
virtual void RequestTrigger(hsBool netRequest=false);
virtual hsBool VerifyConditions(plMessage* msg);
void AddCondition(plConditionalObject* c);
virtual void Reset(bool bCounterReset);
void VolumeIgnoreExtraEnters(bool ignore = true); // hack for garrison
int fMyCursor;
};
#endif // plLogicModifier_inc

View File

@ -0,0 +1,54 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "plMaintainersMarkerModifier.h"
#include "../pnSceneObject/plSceneObject.h"
#include "../plAvatar/plAvatarMgr.h"
void plMaintainersMarkerModifier::AddTarget(plSceneObject* so)
{
plMultiModifier::AddTarget(so);
plAvatarMgr::GetInstance()->AddMaintainersMarker(this);
}
void plMaintainersMarkerModifier::RemoveTarget(plSceneObject* so)
{
plMultiModifier::RemoveTarget(so);
hsAssert(fTargets.GetCount() == 0, "Spawn modifier has multiple targets. Matt.");
plAvatarMgr::GetInstance()->RemoveMaintainersMarker(this);
}
void plMaintainersMarkerModifier::Read(hsStream *stream, hsResMgr *mgr)
{
plMultiModifier::Read(stream, mgr);
stream->ReadSwap(&fCalibrated);
}
void plMaintainersMarkerModifier::Write(hsStream *stream, hsResMgr *mgr)
{
plMultiModifier::Write(stream, mgr);
stream->WriteSwap(fCalibrated);
}

View File

@ -0,0 +1,63 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plMaintainersMarkerModifier_inc
#define plMaintainersMarkerModifier_inc
#include "../pnModifier/plMultiModifier.h"
#include "../pnMessage/plMessage.h"
class plMaintainersMarkerModifier : public plMultiModifier
{
public:
enum
{
kBroken = 0,
kRepaired,
kCalibrated,
};
protected:
virtual hsBool IEval(double secs, hsScalar del, UInt32 dirty) {return true;}
int fCalibrated;
public:
plMaintainersMarkerModifier() : fCalibrated(0){;}
CLASSNAME_REGISTER( plMaintainersMarkerModifier );
GETINTERFACE_ANY( plMaintainersMarkerModifier, plMultiModifier );
virtual void AddTarget(plSceneObject* so);
virtual void RemoveTarget(plSceneObject* so);
void SetCalibrated(hsBool b) {fCalibrated = b;}
int GetCalibrated() { return fCalibrated; }
virtual void Read(hsStream *stream, hsResMgr *mgr);
virtual void Write(hsStream *stream, hsResMgr *mgr);
};
#endif // plMaintainersMarkerModifier_inc

View File

@ -0,0 +1,92 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plModifierCreatable_inc
#define plModifierCreatable_inc
#include "../pnFactory/plCreator.h"
#include "plSpawnModifier.h"
REGISTER_CREATABLE( plSpawnModifier );
#include "plLogicModifier.h"
REGISTER_CREATABLE( plLogicModifier );
#include "plResponderModifier.h"
REGISTER_CREATABLE( plResponderModifier );
REGISTER_CREATABLE( plResponderEnableMsg );
#include "plAxisAnimModifier.h"
REGISTER_CREATABLE( plAxisAnimModifier );
#include "plExcludeRegionModifier.h"
REGISTER_CREATABLE(plExcludeRegionModifier);
REGISTER_CREATABLE(plExcludeRegionSDLModifier);
#include "plSimpleModifier.h"
REGISTER_NONCREATABLE(plSimpleModifier);
#include "plCloneSpawnModifier.h"
REGISTER_CREATABLE(plCloneSpawnModifier);
#include "plAnimEventModifier.h"
REGISTER_CREATABLE(plAnimEventModifier);
#include "plInterfaceInfoModifier.h"
REGISTER_CREATABLE(plInterfaceInfoModifier);
#include "plSDLModifier.h"
REGISTER_NONCREATABLE(plSDLModifier);
#include "plLayerSDLModifier.h"
REGISTER_CREATABLE(plLayerSDLModifier);
#include "plAnimTimeConvertSDLModifier.h"
REGISTER_NONCREATABLE(plAnimTimeConvertSDLModifier);
#include "plResponderSDLModifier.h"
REGISTER_CREATABLE(plResponderSDLModifier);
#include "plSoundSDLModifier.h"
REGISTER_CREATABLE(plSoundSDLModifier);
#include "plDecalEnableMod.h"
REGISTER_CREATABLE(plDecalEnableMod);
#include "plMaintainersMarkerModifier.h"
REGISTER_CREATABLE(plMaintainersMarkerModifier);
#include "plImageLibMod.h"
REGISTER_CREATABLE(plImageLibMod);
#include "plGameMarkerModifier.h"
REGISTER_CREATABLE(plGameMarkerModifier);
#endif // plModifierCreatable_inc

View File

@ -0,0 +1,791 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "hsTypes.h"
#include "hsStlUtils.h"
#include "hsTimer.h"
#include "plResponderModifier.h"
#include "plResponderSDLModifier.h"
#include "plgDispatch.h"
#include "hsResMgr.h"
#include "plPhysical.h"
#include "../pnKeyedObject/plKey.h"
#include "../pnKeyedObject/plFixedKey.h"
#include "../pnSceneObject/plSceneObject.h"
#include "../pnMessage/plNotifyMsg.h"
#include "../pnNetCommon/plNetApp.h"
// for localOnly cmd check
#include "../plMessage/plLinkToAgeMsg.h"
#include "../pnMessage/plCameraMsg.h"
#include "../pnMessage/plSoundMsg.h"
#include "../plMessage/plResponderMsg.h"
#include "../plMessage/plAnimCmdMsg.h"
#include "../plMessage/plLinkToAgeMsg.h"
#include "../pnMessage/plSDLModifierMsg.h"
#include "../../FeatureLib/pfMessage/plArmatureEffectMsg.h"
#include "../plStatusLog/plStatusLog.h"
#include "../plMessage/plTimerCallbackMsg.h"
#include "../pnTimer/plTimerCallbackManager.h"
#include "../plMessage/plSimStateMsg.h"
//#include "../plHavok1\plHKPhysical.h"
//#include "../plHavok1\plHKSubWorld.h"
#include "../plAvatar/plArmatureMod.h"
#include "../plAvatar/plAvatarMgr.h"
//#ifdef HS_DEBUGGING
#define STATUS_LOG
//#endif
#ifdef STATUS_LOG
#define ResponderLog(x) x
#else
#define ResponderLog(x)
#endif
void plResponderEnableMsg::Read(hsStream* stream, hsResMgr* mgr)
{
plMessage::IMsgRead(stream, mgr);
fEnable = stream->Readbool();
}
void plResponderEnableMsg::Write(hsStream* stream, hsResMgr* mgr)
{
plMessage::IMsgWrite(stream, mgr);
stream->Writebool(fEnable);
}
/////////////////////////////////////////////////////
/////////////////////////////////////////////////////
plResponderModifier::plResponderModifier() :
fCurState(0),
fCurCommand(-1),
fEnabled(true),
fFlags(0),
fEnter(false),
fResponderSDLMod(nil),
fGotFirstLoad(false),
fNotifyMsgFlags(0)
{
}
plResponderModifier::~plResponderModifier()
{
delete fResponderSDLMod;
fResponderSDLMod=nil;
for (int i = 0; i < fStates.Count(); i++)
{
for (int j = 0; j < fStates[i].fCmds.Count(); j++ )
hsRefCnt_SafeUnRef(fStates[i].fCmds[j].fMsg);
}
}
hsBool plResponderModifier::MsgReceive(plMessage* msg)
{
plNotifyMsg* pNMsg = plNotifyMsg::ConvertNoRef(msg);
if (pNMsg)
{
if (pNMsg->fType == plNotifyMsg::kResponderFF)
{
ISetResponderStateFromNotify(pNMsg);
IFastForward(true);
}
else if (pNMsg->fType == plNotifyMsg::kResponderChangeState)
{
ISetResponderStateFromNotify(pNMsg);
DirtySynchState(kSDLResponder, 0);
}
else
{
// assumes state of 0 means untriggered and state of 1 is triggered
if ((pNMsg->fState != 0 && (fFlags & kDetectTrigger)) ||
(pNMsg->fState == 0 && (fFlags & kDetectUnTrigger)))
{
Trigger(pNMsg);
DirtySynchState(kSDLResponder, 0);
}
}
return true;
}
plResponderEnableMsg *pEnableMsg = plResponderEnableMsg::ConvertNoRef(msg);
if (pEnableMsg)
{
fEnabled = pEnableMsg->fEnable;
DirtySynchState(kSDLResponder, 0);
return true;
}
plEventCallbackMsg *pEventMsg = plEventCallbackMsg::ConvertNoRef(msg);
plTimerCallbackMsg *timerMsg = plTimerCallbackMsg::ConvertNoRef(msg);
if (pEventMsg || timerMsg)
{
UInt32 waitID = pEventMsg ? pEventMsg->fUser : timerMsg->fID;
if (waitID != -1)
{
// Flag that this callback completed and try sending in case any commands were waiting on this
fCompletedEvents.SetBit(waitID);
ResponderLog(ILog(plStatusLog::kWhite, "Got callback from command %d(id:%d)", ICmdFromWait((Int8)waitID)+1, waitID));
IContinueSending();
DirtySynchState(kSDLResponder, 0);
}
// The is one of the stop callbacks we generated for debug mode
else if (fDebugAnimBox)
IDebugAnimBox(false);
return true;
}
// pass sdl msg to sdlMod
plSDLModifierMsg* sdlMsg = plSDLModifierMsg::ConvertNoRef(msg);
if (sdlMsg && fResponderSDLMod)
{
if (fResponderSDLMod->MsgReceive(sdlMsg))
return true; // msg handled
}
return plSingleModifier::MsgReceive(msg);
}
void plResponderModifier::AddCommand(plMessage* pMsg, int state)
{
fStates[state].fCmds.Append(plResponderCmd(pMsg, -1));
}
void plResponderModifier::AddCallback(Int8 state, Int8 cmd, Int8 callback)
{
fStates[state].fWaitToCmd[callback] = cmd;
}
//
// Decide if this cmd should only be run locally.
// If we are triggered remotely (netRequest==true), then
// we don't want to execute localOnly cmds (like cameraChanges)
//
bool plResponderModifier::IIsLocalOnlyCmd(plMessage* cmd)
{
if (plLinkToAgeMsg::ConvertNoRef(cmd)) // don't want to page out any rooms
return true;
if (plCameraMsg::ConvertNoRef(cmd)) // don't want to change our camera
return true;
plSoundMsg *snd = plSoundMsg::ConvertNoRef( cmd );
if( snd != nil && snd->Cmd( plSoundMsg::kIsLocalOnly ) )
return true;
return false;
}
void plResponderModifier::ISetResponderState(Int8 state)
{
// make sure that it is a valid state to switch to
if (state >= 0 && state < fStates.Count())
{
fCurState = state;
}
else
{
ResponderLog(ILog(plStatusLog::kRed, "Invalid state %d specified, will default to current state", state));
}
}
void plResponderModifier::ISetResponderStateFromNotify(plNotifyMsg* msg)
{
// set the state of the responder IF they want it to be
proResponderStateEventData* event = (proResponderStateEventData*)msg->FindEventRecord(proEventData::kResponderState);
if (event != nil)
ISetResponderState((Int8)(event->fState));
}
void plResponderModifier::Trigger(plNotifyMsg *msg)
{
#if 0
char str[256];
sprintf(str, "RM: Responder %s is triggering, num cmds=%d, enabled=%d, curCmd=%d, t=%f\n",
GetKeyName(), fStates[fCurState].fCmds.GetCount(),
((int)fEnabled), ((int)fCurCommand), hsTimer::GetSysSeconds());
plNetClientApp::GetInstance()->DebugMsg(str);
#endif
// If we're not in the middle of sending, reset and start sending commands
if (fCurCommand == Int8(-1) && fEnabled)
{
ResponderLog(ILog(plStatusLog::kGreen, "Trigger"));
fNotifyMsgFlags = msg->GetAllBCastFlags();
fTriggerer = msg->GetSender();
fPlayerKey = msg->GetAvatarKey();
ISetResponderStateFromNotify(msg);
proCollisionEventData *cEvent = (proCollisionEventData *)msg->FindEventRecord(proEventData::kCollision);
fEnter = (cEvent ? cEvent->fEnter : false);
fCompletedEvents.Reset();
fCurCommand = 0;
DirtySynchState(kSDLResponder, 0);
IContinueSending();
}
else
{
ResponderLog(ILog(plStatusLog::kRed, "Rejected Trigger, %s", !fEnabled ? "responder disabled" : "responder is running"));
}
}
bool plResponderModifier::IContinueSending()
{
// If we haven't been started, exit
if (fCurCommand == Int8(-1))
return false;
plResponderState& state = fStates[fCurState];
while (fCurCommand < state.fCmds.Count())
{
plMessage *msg = state.fCmds[fCurCommand].fMsg;
if (msg)
{
// If this command needs to wait, and it's condition hasn't been met yet, exit
Int8 wait = state.fCmds[fCurCommand].fWaitOn;
if (wait != -1 && !fCompletedEvents.IsBitSet(wait))
{
ResponderLog(ILog(plStatusLog::kWhite, "Command %d is waiting for command %d(id:%d)", Int8(fCurCommand)+1, ICmdFromWait(wait)+1, wait));
return false;
}
if (!(fNotifyMsgFlags & plMessage::kNetNonLocal)|| !IIsLocalOnlyCmd(msg))
{
// make sure outgoing msgs inherit net flags as part of cascade
UInt32 msgFlags = msg->GetAllBCastFlags();
plNetClientApp::InheritNetMsgFlags(fNotifyMsgFlags, &msgFlags, true);
msg->SetAllBCastFlags(msgFlags);
// If this is a responder message, let it know which player triggered this
if (plResponderMsg* responderMsg = plResponderMsg::ConvertNoRef(msg))
{
responderMsg->fPlayerKey = fPlayerKey;
}
else if (plNotifyMsg* notifyMsg = plNotifyMsg::ConvertNoRef(msg))
{
bool foundCollision = false;
// If we find a collision event, this message is meant to trigger a multistage
for (int i = 0; i < notifyMsg->GetEventCount(); i++)
{
proEventData* event = notifyMsg->GetEventRecord(i);
if (event->fEventType == proEventData::kCollision)
{
proCollisionEventData* collisionEvent = (proCollisionEventData*)event;
collisionEvent->fHitter = fPlayerKey;
foundCollision = true;
}
}
// No collision event, this message is for notifying the triggerer
if (!foundCollision)
{
notifyMsg->ClearReceivers();
notifyMsg->AddReceiver(fTriggerer);
}
notifyMsg->SetSender(GetKey());
}
else if (plLinkToAgeMsg* linkMsg = plLinkToAgeMsg::ConvertNoRef(msg))
{
if (linkMsg->GetNumReceivers() == 0)
{
plUoid netUoid(kNetClientMgr_KEY);
plKey netKey = hsgResMgr::ResMgr()->FindKey(netUoid);
hsAssert(netKey,"NetClientMgr not found");
linkMsg->AddReceiver(netKey);
}
}
else if (plArmatureEffectStateMsg* stateMsg = plArmatureEffectStateMsg::ConvertNoRef(msg))
{
stateMsg->ClearReceivers();
stateMsg->AddReceiver(fPlayerKey);
stateMsg->fAddSurface = fEnter;
}
else if (plSubWorldMsg* swMsg = plSubWorldMsg::ConvertNoRef(msg))
{
plArmatureMod *avatar = plAvatarMgr::GetInstance()->GetLocalAvatar();
if(avatar)
{
swMsg->AddReceiver(avatar->GetKey());
}
}
// If we're in anim debug mode, check if this is an anim play
// message so we can put up the cue
if (fDebugAnimBox)
{
plAnimCmdMsg* animMsg = plAnimCmdMsg::ConvertNoRef(msg);
if (animMsg && animMsg->Cmd(plAnimCmdMsg::kContinue))
IDebugPlayMsg(animMsg);
}
if (plTimerCallbackMsg *timerMsg = plTimerCallbackMsg::ConvertNoRef(msg))
{
hsRefCnt_SafeRef(timerMsg);
plgTimerCallbackMgr::NewTimer(timerMsg->fTime, timerMsg);
}
else
{
hsRefCnt_SafeRef(msg);
plgDispatch::MsgSend(msg);
}
}
}
fCurCommand++;
DirtySynchState(kSDLResponder, 0);
}
// Make sure all callbacks we need to wait on are done before allowing a state switch or restart
for (int i = 0; i < state.fNumCallbacks; i++)
{
if (!fCompletedEvents.IsBitSet(i))
{
ResponderLog(ILog(plStatusLog::kWhite, "Can't reset, waiting for command %d(id:%d)", ICmdFromWait(i)+1, i));
return false;
}
}
ResponderLog(ILog(plStatusLog::kGreen, "Reset"));
fCurCommand = -1;
ISetResponderState(state.fSwitchToState);
DirtySynchState(kSDLResponder, 0);
return true;
}
Int8 plResponderModifier::ICmdFromWait(Int8 waitIdx)
{
WaitToCmd& waitToCmd = fStates[fCurState].fWaitToCmd;
if (waitToCmd.find(waitIdx) != waitToCmd.end())
return waitToCmd[waitIdx];
return -1;
}
void plResponderModifier::Restore()
{
// If we're the first player in and we're loading old state where this responder
// was running, fast forward it
if (plNetClientApp::GetInstance()->GetJoinOrder() == 0 && fCurCommand != -1 && !fGotFirstLoad)
{
fGotFirstLoad = true;
IFastForward(false);
return;
}
ResponderLog(ILog(plStatusLog::kGreen, "Load SDL State"));
fGotFirstLoad = true;
plResponderState& state = fStates[fCurState];
for (int i = 0; i < state.fNumCallbacks; i++)
{
if (!fCompletedEvents[i])
{
int cmdIdx = state.fWaitToCmd[i];
plResponderCmd& cmd = state.fCmds[cmdIdx];
//
// If it's a callback message (anim or sound), just send the callbacks again
//
plMessageWithCallbacks* callbackMsg = plMessageWithCallbacks::ConvertNoRef(cmd.fMsg);
if (callbackMsg)
{
// Create a new message for just the callbacks
plMessageWithCallbacks* newCallbackMsg = nil;
if (plAnimCmdMsg* animMsg = plAnimCmdMsg::ConvertNoRef(callbackMsg))
{
plAnimCmdMsg* newAnimMsg = TRACKED_NEW plAnimCmdMsg;
newAnimMsg->SetCmd(plAnimCmdMsg::kAddCallbacks);
newCallbackMsg = newAnimMsg;
ResponderLog(ILog(plStatusLog::kGreen, "Restoring anim callback"));
}
else if (plSoundMsg* soundMsg = plSoundMsg::ConvertNoRef(callbackMsg))
{
plSoundMsg* newSoundMsg = TRACKED_NEW plSoundMsg;
newSoundMsg->SetCmd(plSoundMsg::kAddCallbacks);
newCallbackMsg = newSoundMsg;
ResponderLog(ILog(plStatusLog::kGreen, "Restoring sound callback"));
}
// Setup the sender and receiver
newCallbackMsg->SetSender(callbackMsg->GetSender());
for (int iReceiver = 0; i < callbackMsg->GetNumReceivers(); i++)
newCallbackMsg->AddReceiver(callbackMsg->GetReceiver(iReceiver));
// Add the callbacks
int numCallbacks = callbackMsg->GetNumCallbacks();
for (int iCallback = 0; iCallback < numCallbacks; iCallback++)
{
plMessage* callback = callbackMsg->GetCallback(iCallback);
// hsRefCnt_SafeRef(callback); AddCallback will ref this for us.
newCallbackMsg->AddCallback(callback);
}
newCallbackMsg->Send();
}
}
}
}
#include "plCreatableIndex.h"
plMessage* plResponderModifier::IGetFastForwardMsg(plMessage* msg, bool python)
{
if (!msg)
return nil;
if (plAnimCmdMsg* animMsg = plAnimCmdMsg::ConvertNoRef(msg))
{
if (animMsg->Cmd(plAnimCmdMsg::kContinue) ||
animMsg->Cmd(plAnimCmdMsg::kAddCallbacks))
{
plAnimCmdMsg* newAnimMsg = TRACKED_NEW plAnimCmdMsg;
newAnimMsg->fCmd = animMsg->fCmd;
newAnimMsg->fBegin = animMsg->fBegin;
newAnimMsg->fEnd = animMsg->fEnd;
newAnimMsg->fLoopEnd = animMsg->fLoopEnd;
newAnimMsg->fLoopBegin = animMsg->fLoopBegin;
newAnimMsg->fSpeed = animMsg->fSpeed;
newAnimMsg->fSpeedChangeRate = animMsg->fSpeedChangeRate;
newAnimMsg->fTime = animMsg->fTime;
newAnimMsg->SetAnimName(animMsg->GetAnimName());
newAnimMsg->SetLoopName(animMsg->GetLoopName());
// Remove the callbacks
newAnimMsg->fCmd.SetBit(plAnimCmdMsg::kAddCallbacks, false);
if (newAnimMsg->Cmd(plAnimCmdMsg::kContinue))
{
newAnimMsg->fCmd.SetBit(plAnimCmdMsg::kContinue, false);
newAnimMsg->fCmd.SetBit(plAnimCmdMsg::kFastForward, true);
}
for (int i = 0; i < animMsg->GetNumReceivers(); i++)
newAnimMsg->AddReceiver(animMsg->GetReceiver(i));
ResponderLog(ILog(plStatusLog::kWhite, "FF Animation Play Msg"));
return newAnimMsg;
}
ResponderLog(ILog(plStatusLog::kWhite, "FF Animation Non-Play Msg"));
hsRefCnt_SafeRef(msg);
return msg;
}
else if(plSoundMsg *soundMsg = plSoundMsg::ConvertNoRef(msg))
{
if( fFlags & kSkipFFSound )
{
return nil;
}
if(soundMsg->Cmd(plSoundMsg::kPlay) ||
soundMsg->Cmd(plSoundMsg::kToggleState) ||
soundMsg->Cmd(plAnimCmdMsg::kAddCallbacks))
{
plSoundMsg *newSoundMsg = TRACKED_NEW plSoundMsg;
newSoundMsg->fCmd = soundMsg->fCmd;
newSoundMsg->fBegin = soundMsg->fBegin;
newSoundMsg->fEnd = soundMsg->fEnd;
newSoundMsg->fLoop = soundMsg->fLoop;
newSoundMsg->fSpeed = soundMsg->fSpeed;
newSoundMsg->fTime = soundMsg->fTime;
newSoundMsg->fIndex = soundMsg->fIndex;
newSoundMsg->fRepeats = soundMsg->fRepeats;
newSoundMsg->fPlaying = soundMsg->fPlaying;
newSoundMsg->fNameStr = soundMsg->fNameStr;
newSoundMsg->fVolume = soundMsg->fVolume;
// Remove the callbacks
newSoundMsg->fCmd.SetBit(plSoundMsg::kAddCallbacks, false);
if(newSoundMsg->Cmd(plSoundMsg::kPlay))
{
newSoundMsg->fCmd.SetBit(plSoundMsg::kPlay, false);
newSoundMsg->fCmd.SetBit(plSoundMsg::kFastForwardPlay);
ResponderLog(ILog(plStatusLog::kWhite, "FF Sound Play Msg"));
}
else if(newSoundMsg->Cmd(plSoundMsg::kToggleState))
{
newSoundMsg->fCmd.SetBit(plSoundMsg::kToggleState, false);
newSoundMsg->fCmd.SetBit(plSoundMsg::kFastForwardToggle);
ResponderLog(ILog(plStatusLog::kWhite, "FF Sound Toggle State Msg"));
}
for (int i = 0; i < soundMsg->GetNumReceivers(); i++)
newSoundMsg->AddReceiver(soundMsg->GetReceiver(i));
return newSoundMsg;
}
ResponderLog(ILog(plStatusLog::kWhite, "FF Sound Non-Play/Toggle Msg"));
hsRefCnt_SafeRef(msg);
return msg;
}
else if (msg->ClassIndex() == CLASS_INDEX_SCOPED(plExcludeRegionMsg))
{
ResponderLog(ILog(plStatusLog::kWhite, "FF Exclude Region Msg"));
hsRefCnt_SafeRef(msg);
return msg;
}
else if (msg->ClassIndex() == CLASS_INDEX_SCOPED(plEnableMsg))
{
ResponderLog(ILog(plStatusLog::kWhite, "FF Visibility/Detector Enable Msg"));
hsRefCnt_SafeRef(msg);
return msg;
}
else if (msg->ClassIndex() == CLASS_INDEX_SCOPED(plResponderEnableMsg))
{
ResponderLog(ILog(plStatusLog::kWhite, "FF Responder Enable Msg"));
hsRefCnt_SafeRef(msg);
return msg;
}
else if (msg->ClassIndex() == CLASS_INDEX_SCOPED(plSimSuppressMsg))
{
ResponderLog(ILog(plStatusLog::kWhite, "FF Physical Enable Msg"));
hsRefCnt_SafeRef(msg);
return msg;
}
return nil;
}
void plResponderModifier::IFastForward(bool python)
{
ResponderLog(ILog(plStatusLog::kGreen, "Fast Forward"));
fCurCommand = 0;
plResponderState& state = fStates[fCurState];
while (fCurCommand < state.fCmds.Count())
{
plMessage *msg = state.fCmds[fCurCommand].fMsg;
msg = IGetFastForwardMsg(msg, python);
if (msg)
plgDispatch::MsgSend(msg);
fCurCommand++;
}
ResponderLog(ILog(plStatusLog::kGreen, "Reset"));
fCurCommand = -1;
ISetResponderState(state.fSwitchToState);
plSynchEnabler enable(true);
DirtySynchState(kSDLResponder, 0);
}
void plResponderModifier::Read(hsStream* stream, hsResMgr* mgr)
{
plSingleModifier::Read(stream, mgr);
Int8 numStates = stream->ReadByte();
fStates.SetCount(numStates);
for (Int8 i = 0; i < numStates; i++)
{
plResponderState& state = fStates[i];
state.fNumCallbacks = stream->ReadByte();
state.fSwitchToState = stream->ReadByte();
Int8 j;
Int8 numCmds = stream->ReadByte();
state.fCmds.SetCount(numCmds);
for (j = 0; j < numCmds; j++)
{
plResponderCmd& cmd = state.fCmds[j];
plMessage* pMsg = plMessage::ConvertNoRef(mgr->ReadCreatable(stream));
cmd.fMsg = pMsg;
cmd.fWaitOn = stream->ReadByte();
}
state.fWaitToCmd.clear();
Int8 mapSize = stream->ReadByte();
for (j = 0; j < mapSize; j++)
{
Int8 wait = stream->ReadByte();
Int8 cmd = stream->ReadByte();
state.fWaitToCmd[wait] = cmd;
}
}
ISetResponderState(stream->ReadByte());
fEnabled = stream->Readbool();
fFlags = stream->ReadByte();
// attach responderSDLMod
delete fResponderSDLMod;
fResponderSDLMod = TRACKED_NEW plResponderSDLModifier;
fResponderSDLMod->SetResponder(this);
}
void plResponderModifier::Write(hsStream* stream, hsResMgr* mgr)
{
plSingleModifier::Write(stream, mgr);
Int8 numStates = fStates.GetCount();
stream->WriteByte(numStates);
for (int i = 0; i < numStates; i++)
{
plResponderState& state = fStates[i];
stream->WriteByte(state.fNumCallbacks);
stream->WriteByte(state.fSwitchToState);
Int8 numCmds = state.fCmds.GetCount();
stream->WriteByte(numCmds);
for (int j = 0; j < numCmds; j++)
{
plResponderCmd& cmd = state.fCmds[j];
mgr->WriteCreatable(stream, cmd.fMsg);
stream->WriteByte(cmd.fWaitOn);
}
Int8 mapSize = state.fWaitToCmd.size();
stream->WriteByte(mapSize);
for (WaitToCmd::iterator it = state.fWaitToCmd.begin(); it != state.fWaitToCmd.end(); it++)
{
stream->WriteByte(it->first);
stream->WriteByte(it->second);
}
}
stream->WriteByte(fCurState);
stream->Writebool(fEnabled);
stream->WriteByte(fFlags);
}
#include "../plPipeline/plDebugText.h"
bool plResponderModifier::fDebugAnimBox = false;
void plResponderModifier::IDebugAnimBox(bool start)
{
plDebugText &debugTxt = plDebugText::Instance();
UInt32 scrnWidth, scrnHeight;
debugTxt.GetScreenSize(&scrnWidth, &scrnHeight);
// Box size is 1/8 screen size
UInt32 boxSize = scrnHeight / 8;
// Draw box in lower left corner
if (start)
debugTxt.DrawRect(0, (UInt16)(scrnHeight-boxSize), (UInt16)boxSize, (UInt16)scrnHeight, 0, 255, 0);
else
debugTxt.DrawRect((UInt16)boxSize, (UInt16)(scrnHeight-boxSize), (UInt16)(boxSize*2), (UInt16)scrnHeight, 255, 0, 0);
}
void plResponderModifier::IDebugPlayMsg(plAnimCmdMsg* msg)
{
// Create a stop callback so we can do a cue for that too
plEventCallbackMsg *eventMsg = TRACKED_NEW plEventCallbackMsg;
eventMsg->AddReceiver(GetKey());
eventMsg->fRepeats = 0;
eventMsg->fUser = -1;
eventMsg->fEvent = kStop;
msg->SetCmd(plAnimCmdMsg::kAddCallbacks);
msg->AddCallback(eventMsg);
hsRefCnt_SafeUnRef(eventMsg);
IDebugAnimBox(true);
}
////////////////////////////////////////////////////////////////////////////////
#ifdef STATUS_LOG
static plStatusLog *gLog = nil;
static std::vector<std::string> gNoLogStrings;
#endif // STATUS_LOG
void plResponderModifier::NoLogString(const char* str)
{
#ifdef STATUS_LOG
gNoLogStrings.push_back(str);
#endif // STATUS_LOG
}
void plResponderModifier::ILog(UInt32 color, const char* format, ...)
{
#ifdef STATUS_LOG
if (!gLog)
gLog = plStatusLogMgr::GetInstance().CreateStatusLog(15, "Responder", plStatusLog::kFilledBackground | plStatusLog::kDeleteForMe | plStatusLog::kDontWriteFile | plStatusLog::kAlignToTop);
if (!format || *format == '\0')
return;
const char* keyName = GetKeyName();
// Make sure this key isn't in our list of keys to deny
for (int i = 0; i < gNoLogStrings.size(); i++)
{
if (strncmp(gNoLogStrings[i].c_str(), keyName, gNoLogStrings[i].length()) == 0)
return;
}
// Format the log text
char buf[256];
va_list args;
va_start(args, format);
int numWritten = _vsnprintf(buf, sizeof(buf), format, args);
hsAssert(numWritten > 0, "Buffer too small");
va_end(args);
// Strip the redundant part off the key name
char logLine[512];
const char* modPos = strstr("_ResponderModifier", keyName);
if (modPos)
strncpy(logLine, keyName, modPos - keyName);
else
strcpy(logLine, keyName);
strcat(logLine, ": ");
strcat(logLine, buf);
gLog->AddLine(logLine, color);
#endif // STATUS_LOG
}

View File

@ -0,0 +1,155 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plResponderModifier_inc
#define plResponderModifier_inc
#include "hsStlUtils.h"
#include "../pnModifier/plSingleModifier.h"
#include "../pnMessage/plMessage.h"
class plNotifyMsg;
class plAnimCmdMsg;
class plResponderSDLModifier;
class plResponderModifier : public plSingleModifier
{
friend class plResponderSDLModifier;
protected:
typedef std::map<Int8,Int8> WaitToCmd;
class plResponderCmd
{
public:
plResponderCmd() : fMsg(nil), fWaitOn(-1) {}
plResponderCmd(plMessage *msg, Int8 waitOn) : fMsg(msg), fWaitOn(waitOn) {}
plMessage *fMsg;
Int8 fWaitOn; // Index into fCompletedEvents of who we're waiting on
};
class plResponderState
{
public:
hsTArray<plResponderCmd> fCmds;
Int8 fNumCallbacks; // So we know how far to search into the bitvector to find out when we're done
Int8 fSwitchToState; // State to switch to when all commands complete
WaitToCmd fWaitToCmd;
};
hsTArray<plResponderState> fStates;
Int8 fCurState; // The current state (first index for fCommandList)
Int8 fCurCommand; // The command we are currently waiting to send (or -1 if we're not sending)
bool fNetRequest; // Was the last trigger a net request
hsBitVector fCompletedEvents; // Which events that commands are waiting on have completed
bool fEnabled;
plKey fPlayerKey; // The player who triggered this last
plKey fTriggerer; // Whoever triggered us (for sending notify callbacks)
hsBool fEnter; // Is our current trigger a volume enter?
bool fGotFirstLoad; // Have we gotten our first SDL load?
plResponderSDLModifier* fResponderSDLMod; // handles saving and restoring state
enum
{
kDetectTrigger = 0x1,
kDetectUnTrigger = 0x2,
kSkipFFSound = 0x4
};
UInt8 fFlags;
UInt32 fNotifyMsgFlags; // store the msg flags of the notify which triggered us
void Trigger(plNotifyMsg *msg);
bool IIsLocalOnlyCmd(plMessage* cmd);
bool IContinueSending();
Int8 ICmdFromWait(Int8 waitIdx);
virtual hsBool IEval(double secs, hsScalar del, UInt32 dirty) { return true; }
static bool fDebugAnimBox; // Draws a box on screen when an animation is started
static void IDebugAnimBox(bool start);
void IDebugPlayMsg(plAnimCmdMsg* msg);
// Trigger the responder (regardless of what it's doing) and "fast forward" it to the final state
// If python is true, only run animations
void IFastForward(bool python);
// If the message is FF-able, returns it (or a FF-able version)
plMessage* IGetFastForwardMsg(plMessage* msg, bool python);
void ISetResponderStateFromNotify(plNotifyMsg* msg);
void ISetResponderState(Int8 state);
void ILog(UInt32 color, const char* format, ...);
friend class plResponderComponent;
friend class plResponderWait;
public:
plResponderModifier();
~plResponderModifier();
CLASSNAME_REGISTER( plResponderModifier );
GETINTERFACE_ANY( plResponderModifier, plSingleModifier );
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
virtual hsBool MsgReceive(plMessage* msg);
const plResponderSDLModifier* GetSDLModifier() const { return fResponderSDLMod; }
static bool ToggleDebugAnimBox() { return fDebugAnimBox = !fDebugAnimBox; }
static void NoLogString(const char* str);
// Restore callback state after load
void Restore();
const Int8 GetState() const { return fCurState; }
//
// Export time only
//
void AddCommand(plMessage* pMsg, int state=0);
void AddCallback(Int8 state, Int8 cmd, Int8 callback);
};
// Message for changing the enable state in a responder modifier
class plResponderEnableMsg : public plMessage
{
public:
bool fEnable;
plResponderEnableMsg() : fEnable(true) {}
plResponderEnableMsg(bool enable) : fEnable(enable) {}
CLASSNAME_REGISTER(plResponderEnableMsg);
GETINTERFACE_ANY(plResponderEnableMsg, plMessage);
// IO
void Read(hsStream* stream, hsResMgr* mgr);
void Write(hsStream* stream, hsResMgr* mgr);
};
#endif // plResponderModifier_inc

View File

@ -0,0 +1,160 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "plResponderSDLModifier.h"
#include "../plSDL/plSDL.h"
#include "plResponderModifier.h"
// static vars
char plResponderSDLModifier::kStrCurState[]="curState";
char plResponderSDLModifier::kStrEnabled[]="enabled";
char plResponderSDLModifier::kStrCurCommand[]="curCommand";
char plResponderSDLModifier::kStrNetRequest[]="netRequest";
char plResponderSDLModifier::kStrCompletedEvents[]="completedEvents";
char plResponderSDLModifier::kStrPlayerKey[]="playerKey";
char plResponderSDLModifier::kStrTriggerer[]="triggerer";
plKey plResponderSDLModifier::GetStateOwnerKey() const
{
return fResponder ? fResponder->GetKey() : nil;
}
//
// get current state from responder
// fill out state data rec
//
void plResponderSDLModifier::IPutCurrentStateIn(plStateDataRecord* dstState)
{
hsAssert(fResponder, "nil responder?");
dstState->FindVar(kStrCurState)->Set((int)fResponder->fCurState);
dstState->FindVar(kStrEnabled)->Set(fResponder->fEnabled);
dstState->FindVar(kStrCurCommand)->Set((int)fResponder->fCurCommand);
dstState->FindVar(kStrNetRequest)->Set(fResponder->fNetRequest);
int i;
int num=fResponder->fCompletedEvents.GetNumBitVectors();
dstState->FindVar(kStrCompletedEvents)->Alloc(num);
for(i=0;i<num; i++)
{
int ev = fResponder->fCompletedEvents.GetBitVector(i);
dstState->FindVar(kStrCompletedEvents)->Set(ev, i);
}
dstState->FindVar(kStrPlayerKey)->Set(fResponder->fPlayerKey);
dstState->FindVar(kStrTriggerer)->Set(fResponder->fTriggerer);
}
//
// apply incoming state to responder
//
void plResponderSDLModifier::ISetCurrentStateFrom(const plStateDataRecord* srcState)
{
hsAssert(fResponder, "nil responder?");
int curState = fResponder->fCurState;
int curCommand = fResponder->fCurCommand;
bool enabled = fResponder->fEnabled;
bool netRequest = fResponder->fNetRequest;
hsBitVector completedEvents = fResponder->fCompletedEvents;
plKey playerKey = fResponder->fPlayerKey;
plKey triggerer = fResponder->fTriggerer;
plStateDataRecord::SimpleVarsList vars;
int numVars = srcState->GetUsedVars(&vars);
for (int i = 0; i < numVars; i++)
{
if (vars[i]->IsNamed(kStrCurState))
{
vars[i]->Get(&curState);
}
else if (vars[i]->IsNamed(kStrEnabled))
{
vars[i]->Get(&enabled);
}
else if (vars[i]->IsNamed(kStrCurCommand))
{
vars[i]->Get(&curCommand);
}
else if (vars[i]->IsNamed(kStrNetRequest))
{
vars[i]->Get(&netRequest);
}
else if (vars[i]->IsNamed(kStrCompletedEvents))
{
int numEvents = vars[i]->GetCount();
completedEvents.SetNumBitVectors(numEvents);
for (int j = 0; j < numEvents; j++)
{
int bv;
vars[i]->Get(&bv, j);
completedEvents.SetBitVector(j, bv);
}
}
else if (vars[i]->IsNamed(kStrPlayerKey))
{
vars[i]->Get(&playerKey);
}
else if (vars[i]->IsNamed(kStrTriggerer))
{
vars[i]->Get(&triggerer);
}
else
{
hsAssert(false, "Unknown var name");
}
}
if (numVars)
{
bool stateValid = (curState >= 0 && curState < fResponder->fStates.Count());
hsAssert(stateValid, "Received invalid responder state");
if (!stateValid)
return;
bool cmdValid = curCommand == -1 || (curCommand >= 0 && curCommand < fResponder->fStates[curState].fCmds.Count());
hsAssert(stateValid, "Received invalid responder command");
if (!cmdValid)
return;
// Could try to validate the completed events, but if someone hacked that
// all they could do is set events that we don't look at
fResponder->fCurState = curState;
fResponder->fCurCommand = curCommand;
fResponder->fEnabled = enabled;
fResponder->fNetRequest = netRequest;
fResponder->fCompletedEvents = completedEvents;
fResponder->fPlayerKey = playerKey;
fResponder->fTriggerer = triggerer;
fResponder->Restore();
}
}

View File

@ -0,0 +1,65 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plResponderSDLModifier_inc
#define plResponderSDLModifier_inc
#include "../plModifier/plSDLModifier.h"
//
// This modifier is responsible for sending and recving responder state
//
class plResponderModifier;
class plStateDataRecord;
class plResponderSDLModifier : public plSDLModifier
{
protected:
// var labels
static char kStrCurState[];
static char kStrCurCommand[];
static char kStrNetRequest[];
static char kStrCompletedEvents[];
static char kStrEnabled[];
static char kStrPlayerKey[];
static char kStrTriggerer[];
plResponderModifier* fResponder;
void IPutCurrentStateIn(plStateDataRecord* dstState);
void ISetCurrentStateFrom(const plStateDataRecord* srcState);
public:
CLASSNAME_REGISTER( plResponderSDLModifier );
GETINTERFACE_ANY( plResponderSDLModifier, plSDLModifier);
plResponderSDLModifier() : fResponder(nil) {}
const char* GetSDLName() const { return kSDLResponder; }
plKey GetStateOwnerKey() const;
plResponderModifier* GetResponder() const { return fResponder; }
void SetResponder(plResponderModifier* r) { fResponder=r; AddTarget(nil); }
};
#endif // plResponderSDLModifier_inc

View File

@ -0,0 +1,229 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "plSDLModifier.h"
#include "../pnNetCommon/plSynchedObject.h"
#include "../pnDispatch/plDispatch.h"
#include "../pnSceneObject/plSceneObject.h"
#include "../pnMessage/plSDLModifierMsg.h"
#include "../plNetMessage/plNetMessage.h"
#include "../plSDL/plSDL.h"
#include "../plNetClient/plNetClientMgr.h"
#include "../plNetClient/plNetObjectDebugger.h"
plSDLModifier::plSDLModifier() : fStateCache(nil), fSentOrRecvdState(false)
{
}
plSDLModifier::~plSDLModifier()
{
delete fStateCache;
}
plKey plSDLModifier::GetStateOwnerKey() const
{
return GetTarget() ? GetTarget()->GetKey() : nil;
}
void plSDLModifier::AddTarget(plSceneObject* so)
{
if (so)
plSingleModifier::AddTarget(so);
if (!fStateCache)
fStateCache = TRACKED_NEW plStateDataRecord(GetSDLName());
}
UInt32 plSDLModifier::IApplyModFlags(UInt32 sendFlags)
{
return sendFlags;
}
//
// write to net msg and send to server
//
void plSDLModifier::ISendNetMsg(plStateDataRecord*& state, plKey senderKey, UInt32 sendFlags)
{
hsAssert(senderKey, "nil senderKey?");
plSynchedObject* sobj = plSynchedObject::ConvertNoRef(senderKey->ObjectIsLoaded());
if (sobj && (sobj->IsInSDLVolatileList(GetSDLName())))
state->SetFlags(state->GetFlags() | plStateDataRecord::kVolatile);
bool dirtyOnly = (sendFlags & plSynchedObject::kForceFullSend) == 0;
bool broadcast = (sendFlags & plSynchedObject::kBCastToClients) != 0;
int writeOptions=0;
// if (dirtyOnly)
writeOptions |= plSDL::kDirtyOnly;
if (broadcast)
writeOptions |= plSDL::kBroadcast;
writeOptions |= plSDL::kTimeStampOnRead;
plNetClientMgr::GetInstance()->StoreSDLState(state, senderKey->GetUoid(), sendFlags, writeOptions);
fSentOrRecvdState = true;
}
//
// Process SDL msgs to send and recv state
//
hsBool plSDLModifier::MsgReceive(plMessage* msg)
{
plSDLModifierMsg* sdlMsg = plSDLModifierMsg::ConvertNoRef(msg);
if (sdlMsg && !stricmp(sdlMsg->GetSDLName(),GetSDLName()))
{
UInt32 sendFlags = IApplyModFlags(sdlMsg->GetFlags());
if (!fSentOrRecvdState)
sendFlags |= plSynchedObject::kNewState;
if (sdlMsg->GetAction()==plSDLModifierMsg::kSendToServer)
{
// local player is changing the state and sending it out
plStateChangeNotifier::SetCurrentPlayerID(plNetClientApp::GetInstance()->GetPlayerID());
SendState(sendFlags);
}
else
if (sdlMsg->GetAction()==plSDLModifierMsg::kSendToServerAndClients)
{
// local player is changing the state and sending it out
plStateChangeNotifier::SetCurrentPlayerID(plNetClientApp::GetInstance()->GetPlayerID());
SendState(sendFlags | plSynchedObject::kBCastToClients);
}
else
if (sdlMsg->GetAction()==plSDLModifierMsg::kRecv)
{
plStateDataRecord* sdRec=sdlMsg->GetState();
plStateChangeNotifier::SetCurrentPlayerID(sdlMsg->GetPlayerID()); // remote player changed the state
ReceiveState(sdRec);
}
return true; // consumed
}
return plSingleModifier::MsgReceive(msg);
}
//
// send a state update
//
bool gMooseDump=false;
void plSDLModifier::SendState(UInt32 sendFlags)
{
hsAssert(fStateCache, "nil stateCache");
bool debugObject = (plNetObjectDebugger::GetInstance() &&
plNetObjectDebugger::GetInstance()->IsDebugObject(GetStateOwnerKey()->ObjectIsLoaded()));
bool force = (sendFlags & plSynchedObject::kForceFullSend) != 0;
bool broadcast = (sendFlags & plSynchedObject::kBCastToClients) != 0;
// record current state
plStateDataRecord* curState = TRACKED_NEW plStateDataRecord(GetSDLName());
IPutCurrentStateIn(curState); // return sdl record which reflects current state of sceneObj, dirties curState
if (!force)
{
curState->FlagDifferentState(*fStateCache); // flag items which are different from localCopy as dirty
}
if (curState->IsDirty())
{
// send current state
bool dirtyOnly = force ? false : true;
ISendNetMsg(curState, GetStateOwnerKey(), sendFlags); // send the state
if (debugObject)
{
gMooseDump=true;
plNetObjectDebugger::GetInstance()->SetDebugging(true);
curState->DumpToObjectDebugger(xtl::format("Object %s SENDS SDL state",
GetStateOwnerKey()->GetName(), dirtyOnly).c_str());
gMooseDump=false;
}
// cache current state, send notifications if necessary
fStateCache->UpdateFrom(*curState, dirtyOnly); // update local copy of state
ISentState(curState);
}
delete curState;
if (plNetObjectDebugger::GetInstance())
plNetObjectDebugger::GetInstance()->SetDebugging(false);
}
void plSDLModifier::ReceiveState(const plStateDataRecord* srcState)
{
hsAssert(fStateCache, "nil stateCache");
if (plNetObjectDebugger::GetInstance() &&
plNetObjectDebugger::GetInstance()->IsDebugObject(GetStateOwnerKey()->ObjectIsLoaded()))
{
gMooseDump=true;
plNetObjectDebugger::GetInstance()->SetDebugging(true);
srcState->DumpToObjectDebugger(xtl::format("Object %s RECVS SDL state",
GetStateOwnerKey()->GetName()).c_str());
gMooseDump=false;
}
if (srcState->IsUsed())
{
plSynchEnabler ps(false); // disable dirty tracking while we are receiving/applying state
// apply incoming state
ISetCurrentStateFrom(srcState); // apply incoming state to sceneObj
// cache state, send notifications if necessary
fStateCache->UpdateFrom(*srcState, false); // update local copy of state
fSentOrRecvdState = true;
}
else
{
plNetClientApp::GetInstance()->DebugMsg("\tReceiving and ignoring unused SDL state msg: type %s, object %s",
GetSDLName(), GetStateOwnerKey()->GetName());
}
if (plNetObjectDebugger::GetInstance())
plNetObjectDebugger::GetInstance()->SetDebugging(false);
}
void plSDLModifier::AddNotifyForVar(plKey key, const char* varName, float tolerance) const
{
// create a SDL notifier object
plStateChangeNotifier notifier(tolerance, key);
// set the notification
plStateDataRecord* rec = GetStateCache();
if (rec)
{
plSimpleStateVariable* var = rec->FindVar(varName);
// was the variable found?
if (var)
var->AddStateChangeNotification(notifier);
}
}

View File

@ -0,0 +1,70 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plSDLModifier_inc
#define plSDLModifier_inc
#include "../pnModifier/plSingleModifier.h"
#include "../pnNetCommon/plSDLTypes.h"
//
// Base class for modifiers which send/recv State Desc Language (SDL) messages
//
class plStateDataRecord;
class plSimpleStateVariable;
class plSDLModifier : public plSingleModifier
{
protected:
plStateDataRecord* fStateCache;
bool fSentOrRecvdState;
void ISendNetMsg(plStateDataRecord*& state, plKey senderKey, UInt32 sendFlags); // transmit net msg
virtual void IPutCurrentStateIn(plStateDataRecord* dstState) = 0;
virtual void ISetCurrentStateFrom(const plStateDataRecord* srcState) = 0;
virtual void ISentState(const plStateDataRecord* sentState) {}
hsBool IEval(double secs, hsScalar del, UInt32 dirty) {return false;}
virtual UInt32 IApplyModFlags(UInt32 sendFlags);
public:
CLASSNAME_REGISTER( plSDLModifier );
GETINTERFACE_ANY( plSDLModifier, plSingleModifier);
plSDLModifier();
virtual ~plSDLModifier();
hsBool MsgReceive(plMessage* msg);
void SendState(UInt32 sendFlags); // send a state update
void ReceiveState(const plStateDataRecord* srcState); // recv a state update
virtual const char* GetSDLName() const = 0; // return the string name of the type of state descriptor you handle
virtual plKey GetStateOwnerKey() const;
plStateDataRecord* GetStateCache() const { return fStateCache; }
virtual void AddTarget(plSceneObject* so);
void AddNotifyForVar(plKey key, const char* varName, float tolerance) const;
};
#endif // plSDLModifier_inc

View File

@ -0,0 +1,185 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "hsTypes.h"
#include "plSimpleModifier.h"
#include "plgDispatch.h"
#include "hsStream.h"
#include "../pnSceneObject/plSceneObject.h"
#include "../pnMessage/plTimeMsg.h"
#include "../pnMessage/plRefMsg.h"
#include "hsTimer.h"
// #include "../pfConditional/plAnimationEventConditionalObject.h"
#include "../plMessage/plAnimCmdMsg.h"
plSimpleModifier::plSimpleModifier()
:
fTarget(nil)
{
fTimeConvert.SetOwner(this);
}
plSimpleModifier::~plSimpleModifier()
{
if( !fTimeConvert.IsStopped() )
IEnd();
}
void plSimpleModifier::Read(hsStream* s, hsResMgr* mgr)
{
plModifier::Read(s, mgr);
fTimeConvert.Read(s, mgr);
if( !fTimeConvert.IsStopped() )
IBegin(); // TEMP TILL Message causes IBEGIN
}
void plSimpleModifier::Write(hsStream* s, hsResMgr* mgr)
{
plModifier::Write(s, mgr);
fTimeConvert.Write(s, mgr);
}
void plSimpleModifier::AddTarget(plSceneObject* o)
{
fTarget = o;
if( !fTimeConvert.IsStopped() )
IBegin(); // TEMP TILL Message causes IBEGIN
}
void plSimpleModifier::RemoveTarget(plSceneObject* o)
{
hsAssert(o == fTarget, "Removing target I don't have");
fTarget = nil;
}
void plSimpleModifier::IBegin()
{
if( fTarget )
{
fTimeConvert.Start();
plgDispatch::Dispatch()->RegisterForExactType(plEvalMsg::Index(), GetKey());
}
}
void plSimpleModifier::IEnd()
{
fTimeConvert.Stop();
if( fTarget )
{
plgDispatch::Dispatch()->UnRegisterForExactType(plEvalMsg::Index(), GetKey());
}
}
hsBool plSimpleModifier::IEval(double secs, hsScalar del, UInt32 dirty)
{
return IHandleTime(secs, del);
}
hsBool plSimpleModifier::MsgReceive(plMessage* msg)
{
plRefMsg* refMsg = plRefMsg::ConvertNoRef(msg);
if( refMsg )
{
return IHandleRef(refMsg);
}
plAnimCmdMsg* modMsg = plAnimCmdMsg::ConvertNoRef(msg);
if( modMsg )
{
return IHandleCmd(modMsg);
}
return plModifier::MsgReceive(msg);
}
hsBool plSimpleModifier::IHandleRef(plRefMsg* refMsg)
{
if( refMsg->GetContext() & (plRefMsg::kOnCreate|plRefMsg::kOnRequest|plRefMsg::kOnReplace) )
AddTarget(plSceneObject::ConvertNoRef(refMsg->GetRef()));
else
RemoveTarget(plSceneObject::ConvertNoRef(refMsg->GetRef()));
return true;
}
hsBool plSimpleModifier::IHandleCmd(plAnimCmdMsg* modMsg)
{
hsBool wasStopped = fTimeConvert.IsStopped();
fTimeConvert.HandleCmd(modMsg);
hsBool isStopped = fTimeConvert.IsStopped();
if( wasStopped != isStopped )
{
if( isStopped )
{
IEnd();
}
else
{
IBegin();
}
}
#if 0 // debug
char str[256];
sprintf(str, "ModHandleCmd: time=%f, ts=%f FWD=%d, BWD=%d, SpeedChange=%d sp=%f, CONT=%d, STOP=%d\n",
hsTimer::GetSysSeconds(),
modMsg->GetTimeStamp(),
modMsg->Cmd(plAnimCmdMsg::kSetForewards),
modMsg->Cmd(plAnimCmdMsg::kSetBackwards),
modMsg->Cmd(plAnimCmdMsg::kSetSpeed),
modMsg->fSpeed,
modMsg->Cmd(plAnimCmdMsg::kContinue),
modMsg->Cmd(plAnimCmdMsg::kStop));
hsStatusMessage(str);
#endif
return true;
}
hsBool plSimpleModifier::IHandleTime(double wSecs, hsScalar del)
{
if( !fTarget )
return true;
hsScalar secs = fTimeConvert.WorldToAnimTime(wSecs);
if( secs != fCurrentTime )
{
fCurrentTime = secs;
IApplyDynamic();
}
return true;
}

View File

@ -0,0 +1,94 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plSimpleModifier_inc
#define plSimpleModifier_inc
#include "../pnModifier/plModifier.h"
#include "../pnNetCommon/plSynchedValue.h"
#include "../plInterp/plAnimTimeConvert.h"
class plSceneObject;
class plRefMsg;
class plTimeMsg;
class plAnimCmdMsg;
class plSimpleModifier : public plModifier
{
public:
enum {
kStopped = 0,
kLoop,
kBackwards,
kWrapped,
kNumFlags
};
protected:
plSceneObject* fTarget;
double fLastTime; // in world time
plAnimTimeConvert fTimeConvert;
// The following are in animation time.
hsScalar fCurrentTime;
hsBool IHandleTime(double wSecs, hsScalar del);
hsBool IHandleRef(plRefMsg* refMsg);
virtual hsBool IHandleCmd(plAnimCmdMsg* modMsg);
virtual void IApplyDynamic() = 0;
virtual void IBegin();
virtual void IEnd();
virtual hsBool IEval(double secs, hsScalar del, UInt32 dirty);
public:
plSimpleModifier();
virtual ~plSimpleModifier();
CLASSNAME_REGISTER( plSimpleModifier );
GETINTERFACE_ANY( plSimpleModifier, plModifier);
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
virtual hsBool MsgReceive(plMessage* msg);
virtual int GetNumTargets() const { return fTarget ? 1 : 0; }
virtual plSceneObject* GetTarget(int w) const { /* hsAssert(w < GetNumTargets(), "Bad target"); */ return fTarget; }
virtual void AddTarget(plSceneObject* so);
virtual void RemoveTarget(plSceneObject* so);
virtual plAnimTimeConvert& GetTimeConvert() { return fTimeConvert; }
};
#endif // plSimpleModifier_inc

View File

@ -0,0 +1,130 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "plSoundSDLModifier.h"
#include "../plSDL/plSDL.h"
#include "../pnSceneObject/plSceneObject.h"
#include "../pnSceneObject/plAudioInterface.h"
#include "../plAudio/plSound.h"
// static vars
char plSoundSDLModifier::kStrVolume[]="desiredVolume";
char plSoundSDLModifier::kStrTime[]="time";
char plSoundSDLModifier::kStrPlaying[]="playing";
char plSoundSDLModifier::kStrSounds[]="sounds";
//
// get current state from audio interface
// fill out state data rec
//
void plSoundSDLModifier::IPutCurrentStateIn(plStateDataRecord* dstState)
{
/*plSceneObject* sobj=GetTarget();
hsAssert(sobj, "plSoundSDLModifier, nil target");
const plAudioInterface* ai=sobj->GetAudioInterface();
hsAssert(ai, "nil audio interface");
plSDStateVariable* soundListVar=dstState->FindSDVar(kStrSounds);
int numSounds=ai->GetNumSounds();
soundListVar->Resize(numSounds);
int i;
for(i=0;i<numSounds; i++)
{
plStateDataRecord* soundState=soundListVar->GetStateDataRecord(i);
plSound* sound=ai->GetSound(i);
soundState->FindVar(kStrVolume)->Set(sound->fDesiredVol);
soundState->FindVar(kStrTime)->Set(sound->fVirtualStartTime);
soundState->FindVar(kStrPlaying)->Set(sound->IsPlaying());
}*/
}
//
// apply incoming state to current audio interface
//
void plSoundSDLModifier::ISetCurrentStateFrom(const plStateDataRecord* srcState)
{
plSceneObject* sobj=GetTarget();
hsAssert(sobj, "plSoundSDLModifier, nil target");
const plAudioInterface* ai=sobj->GetAudioInterface();
hsAssert(ai, "nil audio interface");
int numSounds=ai->GetNumSounds();
plSDStateVariable* soundListVar=srcState->FindSDVar(kStrSounds);
if( soundListVar->GetCount() != numSounds )
{
hsAssert( false, "number sounds sounds should not be changing");
return;
}
int i;
for(i=0;i<numSounds;i++)
{
plStateDataRecord* soundState=soundListVar->GetStateDataRecord(i);
plSound* sound=ai->GetSound(i);
float desiredVol;
soundState->FindVar(kStrVolume)->Get(&desiredVol);
//sound->ISetUnsynchedVolume(desiredVol); // MCN CHECK
bool playing;
if (soundState->FindVar(kStrPlaying)->Get(&playing))
{
if (playing)
{
//double timeStarted;
/*if (soundState->FindVar(kStrTime)->Get(&timeStarted))
sound->SynchedPlay((hsScalar)timeStarted);
else
{
// Can't get the time we're supposed to start at, so we'll just try to play normally,
// which should be better than nothing...
hsAssert( false, "No timeStarted state in sound SDL. Bad state from server? Contact MCN *immediately*" );
sound->Play();
}*/
}
else
{
if( sound->IsPropertySet( plSound::kPropAutoStart ) )
{
#if 0
// There is a sound in teledahn (swampAmb) which leggaly has this behavior
hsAssert( false, "Auto-start sound just got a state update telling it to stop. "
"This is technically legal, but so far there isn't any case where this should "
"happen. Further, it's very likely to be the cause of the very-intermittent "
"auto-start-sounds-not-playing bug. Leave this up and contact MCN *immediately*" );
#endif
}
//sound->IStop();
}
}
}
}

View File

@ -0,0 +1,54 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plSoundSDLModifier_inc
#define plSoundSDLModifier_inc
#include "../plModifier/plSDLModifier.h"
//
// This modifier is responsible for sending and recving
// an object's audio state.
//
class plStateDataRecord;
class plSoundSDLModifier : public plSDLModifier
{
protected:
// var labels
static char kStrVolume[];
static char kStrTime[];
static char kStrPlaying[];
static char kStrSounds[];
void IPutCurrentStateIn(plStateDataRecord* dstState);
void ISetCurrentStateFrom(const plStateDataRecord* srcState);
public:
CLASSNAME_REGISTER( plSoundSDLModifier );
GETINTERFACE_ANY( plSoundSDLModifier, plSDLModifier);
const char* GetSDLName() const { return kSDLSound; }
};
#endif // plSoundSDLModifier_inc

View File

@ -0,0 +1,85 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
//#include "hsTypes.h"
//#include "hsGeometry3.h"
//#include "plgDispatch.h"
//#include "../pnSceneObject/plDrawInterface.h"
//#include "../pnSceneObject/plCoordinateInterface.h"
//#include "hsBounds.h"
#include "plSpawnModifier.h"
#include "../pnSceneObject/plSceneObject.h"
#include "../plAvatar/plAvatarMgr.h"
//#include "../pnMessage/plTimeMsg.h"
//#include "../pnKeyedObject/plKey.h"
//#include "../plMessage/plSpawnRequestMsg.h"
//#include "../plMessage/plSpawnModMsg.h"
//hsBool plSpawnModifier::MsgReceive(plMessage* msg)
//{
// plSpawnRequestMsg* pSpawnMsg = plSpawnRequestMsg::ConvertNoRef(msg);
// if (pSpawnMsg)
// {
// fTargets.GetCount();
// for (int i=0; i < GetNumTargets(); i++)
// {
// plSpawnModMsg* pMsg = NEW(plSpawnModMsg);
// pMsg->AddReceiver( pSpawnMsg->GetSender() );
// //pMsg->fPos= GetTarget(i)->GetDrawInterface()->GetWorldBounds().GetCenter();
// pMsg->fPos= GetTarget(i)->GetCoordinateInterface()->GetLocalToWorld().GetTranslate();
// pMsg->fObj = GetTarget(i)->GetKey()->GetUoid();
// plgDispatch::MsgSend( pMsg );
// }
// return true;
// }
// return plMultiModifier::MsgReceive(msg);
//}
void plSpawnModifier::AddTarget(plSceneObject* so)
{
plMultiModifier::AddTarget(so);
plAvatarMgr::GetInstance()->AddSpawnPoint(this);
// plgDispatch::Dispatch()->RegisterForExactType(plSpawnRequestMsg::Index(), GetKey());
}
void plSpawnModifier::RemoveTarget(plSceneObject* so)
{
plMultiModifier::RemoveTarget(so);
hsAssert(fTargets.GetCount() == 0, "Spawn modifier has multiple targets. Matt.");
plAvatarMgr::GetInstance()->RemoveSpawnPoint(this);
}
void plSpawnModifier::Read(hsStream *stream, hsResMgr *mgr)
{
plMultiModifier::Read(stream, mgr);
}
void plSpawnModifier::Write(hsStream *stream, hsResMgr *mgr)
{
plMultiModifier::Write(stream, mgr);
}

View File

@ -0,0 +1,54 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plSpawnModifier_inc
#define plSpawnModifier_inc
#include "../pnModifier/plMultiModifier.h"
#include "../pnMessage/plMessage.h"
class plSpawnModifier : public plMultiModifier
{
protected:
virtual hsBool IEval(double secs, hsScalar del, UInt32 dirty) {return true;}
public:
plSpawnModifier(){;}
CLASSNAME_REGISTER( plSpawnModifier );
GETINTERFACE_ANY( plSpawnModifier, plMultiModifier );
virtual void AddTarget(plSceneObject* so);
virtual void RemoveTarget(plSceneObject* so);
// hsBool MsgReceive(plMessage* msg);
//
virtual void Read(hsStream *stream, hsResMgr *mgr);
virtual void Write(hsStream *stream, hsResMgr *mgr);
};
#endif // plSpawnModifier_inc

View File

@ -0,0 +1,103 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "plTagModifier.h"
#include "hsResMgr.h"
#include "../pnMessage/plRemoteAvatarInfoMsg.h"
#include "../plMessage/plAvatarMsg.h"
//#include "../pfMessage/plClothingMsg.h"
#include "../plMessage/plCollideMsg.h"
#include "../plMessage/plSimInfluenceMsg.h"
#include "../plStatusLog/plStatusLog.h"
static plStatusLog* gLog = nil;
plTagModifier::plTagModifier()
{
if (!gLog)
gLog = plStatusLogMgr::GetInstance().CreateStatusLog(15, "Tag", plStatusLog::kFilledBackground | plStatusLog::kDeleteForMe | plStatusLog::kDontWriteFile | plStatusLog::kAlignToTop);
}
plTagModifier::~plTagModifier()
{
}
hsBool plTagModifier::MsgReceive(plMessage* msg)
{
plCollideMsg* collideMsg = plCollideMsg::ConvertNoRef(msg);
if (collideMsg)
{
gLog->AddLineF("Kicked by %s", collideMsg->fOtherKey->GetName());
return true;
}
plRemoteAvatarInfoMsg* avInfoMsg = plRemoteAvatarInfoMsg::ConvertNoRef(msg);
if (avInfoMsg)
{
// TODO
// Check if the local av is frozen
// plKey localAvKey = plNetClientMgr::GetInstance()->GetLocalPlayerKey();
// Freeze clicked av
plKey clickedAvKey = avInfoMsg->GetAvatarKey();
if (clickedAvKey)
{
static hsBool tempHack = true;
tempHack = !tempHack;
plAvEnableMsg* avEnableMsg = new plAvEnableMsg(GetKey(), clickedAvKey, tempHack);
avEnableMsg->SetBCastFlag(plMessage::kNetPropagate | plMessage::kPropagateToModifiers);
avEnableMsg->Send();
gLog->AddLineF("Tagged %s", clickedAvKey->GetName());
}
return true;
}
return plSingleModifier::MsgReceive(msg);
}
void plTagModifier::Read(hsStream* stream, hsResMgr* mgr)
{
plSingleModifier::Read(stream, mgr);
}
void plTagModifier::Write(hsStream* stream, hsResMgr* mgr)
{
plSingleModifier::Write(stream, mgr);
}
#include "plgDispatch.h"
void plTagModifier::SetTarget(plSceneObject* so)
{
if (so)
plgDispatch::Dispatch()->RegisterForExactType(plRemoteAvatarInfoMsg::Index(), GetKey());
else
plgDispatch::Dispatch()->UnRegisterForExactType(plRemoteAvatarInfoMsg::Index(), GetKey());
}

View File

@ -0,0 +1,51 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plTagModifier_inc
#define plTagModifier_inc
#include "../pnModifier/plSingleModifier.h"
class plTagModifier : public plSingleModifier
{
protected:
virtual hsBool IEval(double secs, hsScalar del, UInt32 dirty) { return true; }
public:
plTagModifier();
virtual ~plTagModifier();
CLASSNAME_REGISTER(plTagModifier);
GETINTERFACE_ANY(plTagModifier, plSingleModifier);
virtual hsBool MsgReceive(plMessage* msg);
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
virtual void SetTarget(plSceneObject* so);
};
#endif // plTagModifier_inc