1
0
mirror of https://foundry.openuru.org/gitblit/r/CWE-ou-minkata.git synced 2025-07-18 11:19:10 +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 b970ae4bad
3976 changed files with 1301355 additions and 0 deletions

View File

@ -0,0 +1,46 @@
/*==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 pfAllCreatables_inc
#define pfAllCreatables_inc
#include "../pfCharacter/pfCharacterCreatable.h"
#include "../pfCamera/pfCameraCreatable.h"
#include "../pfAnimation/pfAnimationCreatable.h"
#include "../pfConditional/plConditionalObjectCreatable.h"
#include "../pfConsole/pfConsoleCreatable.h"
#include "../pfSurface/pfSurfaceCreatable.h"
#include "../pfMessage/pfMessageCreatable.h"
#include "../pfAudio/pfAudioCreatable.h"
#include "../pfPython/pfPythonCreatable.h"
#include "../pfGameGUIMgr/pfGameGUIMgrCreatable.h"
#include "../pfCCR/plCCRCreatable.h"
#include "../pfJournalBook/pfJournalBookCreatable.h"
#include "../pfGameMgr/pfGameMgrCreatables.h"
#include "../pfSecurePreloader/pfSecurePreloaderCreatable.h"
#endif // pfAllCreatables_inc

View File

@ -0,0 +1,72 @@
/*==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 pfAnimationCreatable_inc
#define pfAnimationCreatable_inc
#include "../pnFactory/plCreator.h"
#include "plViewFaceModifier.h"
REGISTER_CREATABLE( plViewFaceModifier );
#include "plLineFollowMod.h"
REGISTER_CREATABLE( plLineFollowMod );
REGISTER_CREATABLE( plRailCameraMod );
#include "plLightModifier.h"
REGISTER_CREATABLE( plLightModifier );
REGISTER_CREATABLE( plOmniModifier );
REGISTER_CREATABLE( plSpotModifier );
REGISTER_CREATABLE( plLtdDirModifier );
#include "plRandomCommandMod.h"
REGISTER_NONCREATABLE( plRandomCommandMod );
#include "plFollowMod.h"
REGISTER_CREATABLE( plFollowMod );
#include "plBlower.h"
REGISTER_CREATABLE( plBlower );
#include "plFilterCoordInterface.h"
REGISTER_CREATABLE( plFilterCoordInterface );
#include "plStereizer.h"
REGISTER_CREATABLE( plStereizer );
#include "pfObjectFlocker.h"
REGISTER_CREATABLE( pfObjectFlocker );
#endif // pfAnimationCreatable_inc

View File

@ -0,0 +1,438 @@
/*==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 OBJECT_FLOCKER_H
#define OBJECT_FLOCKER_H
#include "../pnModifier/plSingleModifier.h"
class hsStream;
class hsResMgr;
class plRandom;
class pfObjectFlocker;
// Database tokens for our prox database
template <class T>
class pfTokenForProximityDatabase
{
public:
virtual ~pfTokenForProximityDatabase() {}
// call this when your position changes
virtual void UpdateWithNewPosition(const hsPoint3 &newPos) = 0;
// find all close-by objects (determined by center and radius)
virtual void FindNeighbors(const hsPoint3 &center, const float radius, std::vector<T> &results) = 0;
};
// A basic prox database (might need to be optimized in the future)
template <class T>
class pfBasicProximityDatabase
{
public:
class tokenType;
typedef std::vector<tokenType*> tokenVector;
typedef typename tokenVector::const_iterator tokenIterator;
// "token" to represent objects stored in the database
class tokenType: public pfTokenForProximityDatabase<T>
{
private:
tokenVector& fTokens;
T fParent;
hsPoint3 fPosition;
public:
// constructor
tokenType(T parentObject, tokenVector& tokens) : fParent(parentObject), fTokens(tokens)
{
fTokens.push_back(this);
}
// destructor
virtual ~tokenType()
{
// remove this token from the database's vector
fTokens.erase(std::find(fTokens.begin(), fTokens.end(), this));
}
// call this when your position changes
void UpdateWithNewPosition(const hsPoint3 &newPosition) {fPosition = newPosition;}
// find all close-by objects (determined by center and radius)
void FindNeighbors(const hsPoint3 &center, const float radius, std::vector<T> & results)
{
// take the slow way, loop and check every one
const float radiusSquared = radius * radius;
for (tokenIterator i = fTokens.begin(); i != fTokens.end(); i++)
{
const hsVector3 offset(&center, &((**i).fPosition));
const float distanceSquared = offset.MagnitudeSquared();
// push onto result vector when within given radius
if (distanceSquared < radiusSquared)
results.push_back((**i).fParent);
}
}
};
private:
// STL vector containing all tokens in database
tokenVector fGroup;
public:
// constructor
pfBasicProximityDatabase(void) {}
// destructor
virtual ~pfBasicProximityDatabase() {}
// allocate a token to represent a given client object in this database
tokenType *MakeToken(T parentObject) {return TRACKED_NEW tokenType(parentObject, fGroup);}
// return the number of tokens currently in the database
int Size(void) {return group.size();}
};
// A basic vehicle class that handles accelleration, braking, and turning
class pfVehicle
{
private:
hsPoint3 fPos; // position in meters
hsPoint3 fLastPos; // the last position we had
hsPoint3 fSmoothedPosition;
hsVector3 fVel; // velocity in meters/second
hsVector3 fSmoothedAcceleration;
hsVector3 fForward; // forward vector (unit length)
hsVector3 fLastForward; // the last forward vector we had
hsVector3 fSide; // side vector (unit length)
hsVector3 fUp; // up vector (unit length)
float fSpeed; // speed (length of velocity vector)
float fMass; // mass of the object (defaults to 1)
float fMaxForce; // the maximum steering force that can be applied
float fMaxSpeed; // the maximum speed of this vehicle
float fCurvature;
float fSmoothedCurvature;
float fRadius;
// measure the path curvature (1/turning radius), maintain smoothed version
void IMeasurePathCurvature(const float elapsedTime);
public:
pfVehicle() {Reset();}
virtual ~pfVehicle() {}
void Reset();
// get/set attributes
float Mass() const {return fMass;}
float SetMass(float m) {return fMass = m;}
hsVector3 Forward() const {return fForward;}
hsVector3 SetForward(hsVector3 forward) {return fForward = forward;}
hsVector3 Side() const {return fSide;}
hsVector3 SetSide(hsVector3 side) {return fSide = side;}
hsVector3 Up() const {return fUp;}
hsVector3 SetUp(hsVector3 up) {return fUp = up;}
hsPoint3 Position() const {return fPos;}
hsPoint3 SetPosition(hsPoint3 pos) {return fPos = pos;}
hsVector3 Velocity() const {return Forward() * fSpeed;}
float Speed() const {return fSpeed;}
float SetSpeed(float speed) {return fSpeed = speed;}
float MaxForce() const {return fMaxForce;}
float SetMaxForce(float maxForce) {return fMaxForce = maxForce;}
float MaxSpeed() const {return fMaxSpeed;}
float SetMaxSpeed(float maxSpeed) {return fMaxSpeed = maxSpeed;}
float Curvature() const {return fCurvature;}
float SmoothedCurvature() {return fSmoothedCurvature;}
float ResetSmoothedCurvature(float value = 0);
hsVector3 SmoothedAcceleration() {return fSmoothedAcceleration;}
hsVector3 ResetSmoothedAcceleration(const hsVector3 &value = hsVector3(0,0,0));
hsPoint3 SmoothedPosition() {return fSmoothedPosition;}
hsPoint3 ResetSmoothedPosition(const hsPoint3 &value = hsPoint3(0,0,0));
float Radius() const {return fRadius;}
float SetRadius(float radius) {return fRadius = radius;}
// Basic geometry functions
// Reset local space to identity
void ResetLocalSpace();
// Set the side vector to a normalized cross product of forward and up
void SetUnitSideFromForwardAndUp();
// Regenerate orthonormal basis vectors given a new forward vector (unit length)
void RegenerateOrthonormalBasisUF(const hsVector3 &newUnitForward);
// If the new forward is NOT known to have unit length
void RegenerateOrthonormalBasis(const hsVector3 &newForward)
{hsVector3 temp = newForward; temp.Normalize(); RegenerateOrthonormalBasisUF(temp);}
// For supplying both a new forward, and a new up
void RegenerateOrthonormalBasis(const hsVector3 &newForward, const hsVector3 &newUp)
{fUp = newUp; RegenerateOrthonormalBasis(newForward);}
// Keep forward parallel to velocity, change up as little as possible
virtual void RegenerateLocalSpace(const hsVector3 &newVelocity, const float elapsedTime);
// Keep forward parallel to velocity, but "bank" the up vector
void RegenerateLocalSpaceForBanking(const hsVector3 &newVelocity, const float elapsedTime);
// Vehicle physics functions
// apply a steering force to our momentum and adjust our
// orientation to match our velocity vector
void ApplySteeringForce(const hsVector3 &force, const float deltaTime);
// adjust the steering force passed to ApplySteeringForce (so sub-classes can refine)
// by default, we won't allow backward-facing steering at a low speed
virtual hsVector3 AdjustRawSteeringForce(const hsVector3 &force, const float deltaTime);
// apply a braking force
void ApplyBrakingForce(const float rate, const float deltaTime);
// predict the position of the vehicle (assumes constant velocity)
hsPoint3 PredictFuturePosition(const float predictionTime);
};
// A goal object, basically keeps track of a scene object so we can get velocity from it
class pfBoidGoal
{
private:
hsPoint3 fLastPos;
hsPoint3 fCurPos;
hsVector3 fForward;
float fSpeed; // in meters/sec
hsBool fHasLastPos; // does the last position make sense?
public:
pfBoidGoal();
~pfBoidGoal() {}
void Update(plSceneObject *goal, float deltaTime);
hsPoint3 Position() const {return fCurPos;}
float Speed() const {return fSpeed;}
hsVector3 Forward() const {return fForward;}
hsPoint3 PredictFuturePosition(const float predictionTime);
};
typedef pfTokenForProximityDatabase<pfVehicle*> pfProximityToken;
typedef pfBasicProximityDatabase<pfVehicle*> pfProximityDatabase;
// The actual "flocking following" (not really a boid, but whatever)
class pfBoid: public pfVehicle
{
private:
plKey fObjKey;
float fWanderSide;
float fWanderUp;
float fGoalWeight;
float fRandomWeight;
float fSeparationRadius;
float fSeparationAngle;
float fSeparationWeight;
float fCohesionRadius;
float fCohesionAngle;
float fCohesionWeight;
pfProximityToken* fProximityToken;
std::vector<pfVehicle*> fNeighbors;
// Set our flocking settings to default
void IFlockDefaults();
// Setup our prox database token
void ISetupToken(pfProximityDatabase &pd);
// Are we in the neighborhood of another boid?
hsBool IInBoidNeighborhood(const pfVehicle &other, const float minDistance, const float maxDistance, const float cosMaxAngle);
// Wander steering
hsVector3 ISteerForWander(float timeDelta);
// Seek the target point
hsVector3 ISteerForSeek(const hsPoint3 &target);
// Steer the boid toward our goal
hsVector3 ISteerToGoal(pfBoidGoal &goal, float maxPredictionTime);
// Steer to keep separation
hsVector3 ISteerForSeparation(const float maxDistance, const float cosMaxAngle, const std::vector<pfVehicle*> &flock);
// Steer to keep the flock together
hsVector3 ISteerForCohesion(const float maxDistance, const float cosMaxAngle, const std::vector<pfVehicle*> &flock);
public:
pfObjectFlocker *fFlockerPtr;
pfBoid(pfProximityDatabase &pd, pfObjectFlocker *flocker, plKey &key);
pfBoid(pfProximityDatabase &pd, pfObjectFlocker *flocker, plKey &key, hsPoint3 &pos);
pfBoid(pfProximityDatabase &pd, pfObjectFlocker *flocker, plKey &key, hsPoint3 &pos, float speed, hsVector3 &forward, hsVector3 &side, hsVector3 &up);
virtual ~pfBoid();
// Get/set functions
float GoalWeight() const {return fGoalWeight;}
float SetGoalWeight(float goalWeight) {return fGoalWeight = goalWeight;}
float WanderWeight() const {return fRandomWeight;}
float SetWanderWeight(float wanderWeight) {return fRandomWeight = wanderWeight;}
float SeparationWeight() const {return fSeparationWeight;}
float SetSeparationWeight(float weight) {return fSeparationWeight = weight;}
float SeparationRadius() const {return fSeparationRadius;}
float SetSeparationRadius(float radius) {return fSeparationRadius = radius;}
float CohesionWeight() const {return fCohesionWeight;}
float SetCohesionWeight(float weight) {return fCohesionWeight = weight;}
float CohesionRadius() const {return fCohesionRadius;}
float SetCohesionRadius(float radius) {return fCohesionRadius = radius;}
// Update the boid's data based on the goal and time delta
void Update(pfBoidGoal &goal, float deltaTime);
plKey &GetKey() {return fObjKey;}
// We're redirecting this to the "banking" function
virtual void RegenerateLocalSpace(const hsVector3 &newVelocity, const float elapsedTime);
};
class pfFlock
{
private:
std::vector<pfBoid*> fBoids;
pfBoidGoal fBoidGoal;
pfProximityDatabase *fDatabase;
// global values so when we add a boid we can set it's parameters
float fGoalWeight, fRandomWeight;
float fSeparationWeight, fSeparationRadius;
float fCohesionWeight, fCohesionRadius;
float fMaxForce; // max steering force
float fMaxSpeed, fMinSpeed;
public:
pfFlock();
~pfFlock();
// Get/set functions (affect the whole flock, and any new boids added)
float GoalWeight() const {return fGoalWeight;}
void SetGoalWeight(float goalWeight);
float WanderWeight() const {return fRandomWeight;}
void SetWanderWeight(float wanderWeight);
float SeparationWeight() const {return fSeparationWeight;}
void SetSeparationWeight(float weight);
float SeparationRadius() const {return fSeparationRadius;}
void SetSeparationRadius(float radius);
float CohesionWeight() const {return fCohesionWeight;}
void SetCohesionWeight(float weight);
float CohesionRadius() const {return fCohesionRadius;}
void SetCohesionRadius(float radius);
float MaxForce() const {return fMaxForce;}
void SetMaxForce(float force);
float MaxSpeed() const {return fMaxSpeed;}
void SetMaxSpeed(float speed);
float MinSpeed() const {return fMinSpeed;}
void SetMinSpeed(float minSpeed);
// setup/run functions
void AddBoid(pfObjectFlocker *flocker, plKey &key, hsPoint3 &pos);
void Update(plSceneObject *goal, float deltaTime);
pfBoid *GetBoid(int i);
friend class pfObjectFlocker;
};
class pfObjectFlocker : public plSingleModifier
{
public:
pfObjectFlocker();
~pfObjectFlocker();
CLASSNAME_REGISTER( pfObjectFlocker );
GETINTERFACE_ANY( pfObjectFlocker, plSingleModifier );
virtual void SetTarget(plSceneObject* so);
virtual hsBool MsgReceive(plMessage* msg);
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
void SetNumBoids(UInt8 val);
void SetBoidKey(plKey key) { fBoidKey = key; }
float GoalWeight() const {return fFlock.GoalWeight();}
void SetGoalWeight(float goalWeight) {fFlock.SetGoalWeight(goalWeight);}
float WanderWeight() const {return fFlock.WanderWeight();}
void SetWanderWeight(float wanderWeight) {fFlock.SetWanderWeight(wanderWeight);}
float SeparationWeight() const {return fFlock.SeparationWeight();}
void SetSeparationWeight(float weight) {fFlock.SetSeparationWeight(weight);}
float SeparationRadius() const {return fFlock.SeparationRadius();}
void SetSeparationRadius(float radius) {fFlock.SetSeparationRadius(radius);}
float CohesionWeight() const {return fFlock.CohesionWeight();}
void SetCohesionWeight(float weight) {fFlock.SetCohesionWeight(weight);}
float CohesionRadius() const {return fFlock.CohesionRadius();}
void SetCohesionRadius(float radius) {fFlock.SetCohesionRadius(radius);}
float MaxForce() const {return fFlock.MaxForce();}
void SetMaxForce(float force) {fFlock.SetMaxForce(force);}
float MaxSpeed() const {return fFlock.MaxSpeed();}
void SetMaxSpeed(float speed) {fFlock.SetMaxSpeed(speed);}
float MinSpeed() const {return fFlock.MinSpeed();}
void SetMinSpeed(float minSpeed) {fFlock.SetMinSpeed(minSpeed);}
hsBool RandomizeAnimStart() const {return fRandomizeAnimationStart;}
void SetRandomizeAnimStart(hsBool val) {fRandomizeAnimationStart = val;}
hsBool UseTargetRotation() const {return fUseTargetRotation;}
void SetUseTargetRotation(hsBool val) {fUseTargetRotation = val;}
protected:
const static int fFileVersion; // so we don't have to update the global version number when we change
pfFlock fFlock;
int fNumBoids;
plKey fBoidKey;
hsBool fUseTargetRotation;
hsBool fRandomizeAnimationStart;
virtual hsBool IEval(double secs, hsScalar del, UInt32 dirty);
};
#endif

View File

@ -0,0 +1,149 @@
/*==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 "hsStlUtils.h"
#include "hsResMgr.h"
#include "hsTemplates.h"
#include "hsTimer.h"
#include "plAnimDebugList.h"
#include "../pnSceneObject/plSceneObject.h"
#include "../plSurface/hsGMaterial.h"
#include "../plSurface/plLayerAnimation.h"
#include "../plAvatar/plAGMasterMod.h"
#include "../plAvatar/plAGAnimInstance.h"
#include "../plAvatar/plAGAnim.h"
#include "../plResMgr/plKeyFinder.h"
#include "../plPipeline/plDebugText.h"
void plAnimDebugList::AddObjects(char *subString)
{
std::vector<plKey> keys;
std::vector<plKey>::iterator i;
plKeyFinder::Instance().ReallyStupidSubstringSearch(subString, hsGMaterial::Index(), keys);
for (i = keys.begin(); i != keys.end(); i++)
{
if (fMaterialKeys.Find((*i)) == fMaterialKeys.kMissingIndex)
fMaterialKeys.Append((*i));
}
keys.clear();
plKeyFinder::Instance().ReallyStupidSubstringSearch(subString, plSceneObject::Index(), keys);
for (i = keys.begin(); i != keys.end(); i++)
{
plSceneObject *so = plSceneObject::ConvertNoRef((*i)->ObjectIsLoaded());
if (so)
{
const plAGMasterMod *agMod = plAGMasterMod::ConvertNoRef(so->GetModifierByType(plAGMasterMod::Index()));
if (agMod && fSOKeys.Find(so->GetKey()) == fSOKeys.kMissingIndex)
fSOKeys.Append(so->GetKey());
}
}
}
void plAnimDebugList::RemoveObjects(char *subString)
{
int i;
for (i = fMaterialKeys.GetCount() - 1; i >= 0; i--)
{
if (strstr(fMaterialKeys[i]->GetName(), subString))
fMaterialKeys.Remove(i);
}
for (i = fSOKeys.GetCount() - 1; i >= 0; i--)
{
if (strstr(fSOKeys[i]->GetName(), subString))
fSOKeys.Remove(i);
}
}
void plAnimDebugList::ShowReport()
{
if (!fEnabled)
return;
plDebugText &txt = plDebugText::Instance();
int y,x,i,j;
const int yOff=10, startY=40, startX=10;
char str[256];
x = startX;
y = startY;
txt.DrawString(x, y, "Material Animations:", 255, 255, 255, 255, plDebugText::kStyleBold);
y += yOff;
for (i = 0; i < fMaterialKeys.GetCount(); i++)
{
hsGMaterial *mat = hsGMaterial::ConvertNoRef(fMaterialKeys[i]->ObjectIsLoaded());
if (!mat)
continue;
for (j = 0; j < mat->GetNumLayers(); j++)
{
plLayerInterface *layer = mat->GetLayer(j)->BottomOfStack();
while (layer != nil)
{
plLayerAnimation *layerAnim = plLayerAnimation::ConvertNoRef(layer);
if (layerAnim)
{
sprintf(str, "%s: %s %.3f (%.3f)", mat->GetKeyName(), layerAnim->GetKeyName(),
layerAnim->GetTimeConvert().CurrentAnimTime(),
layerAnim->GetTimeConvert().WorldToAnimTimeNoUpdate(hsTimer::GetSysSeconds()));
txt.DrawString(x, y, str);
y += yOff;
}
layer = layer->GetOverLay();
}
}
}
y += yOff;
txt.DrawString(x, y, "AGMaster Anims", 255, 255, 255, 255, plDebugText::kStyleBold);
y += yOff;
for (i = 0; i < fSOKeys.GetCount(); i++)
{
plSceneObject *so = plSceneObject::ConvertNoRef(fSOKeys[i]->ObjectIsLoaded());
if (!so)
continue;
plAGMasterMod *mod = const_cast<plAGMasterMod*>(plAGMasterMod::ConvertNoRef(so->GetModifierByType(plAGMasterMod::Index())));
if (!mod)
continue;
sprintf(str, " %s", so->GetKeyName());
txt.DrawString(x, y, str);
y += yOff;
for (j = 0; j < mod->GetNumATCAnimations(); j++)
{
plAGAnimInstance *anim = mod->GetATCAnimInstance(j);
sprintf(str, " %s: %.3f (%.3f)", anim->GetAnimation()->GetName(),
anim->GetTimeConvert()->CurrentAnimTime(),
anim->GetTimeConvert()->WorldToAnimTimeNoUpdate(hsTimer::GetSysSeconds()));
txt.DrawString(x, y, str);
y += yOff;
}
}
}

View File

@ -0,0 +1,47 @@
/*==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 plAnimDebugList_inc
#define plAnimDebugList_inc
// Simple debugging tool, everything is public
// This class collects a list of keyed objects that deal with
// animation, to report info on them when requested.
class plAnimDebugList
{
public:
hsBool fEnabled;
hsTArray<plKey> fSOKeys;
hsTArray<plKey> fMaterialKeys;
plAnimDebugList() : fEnabled(false) {}
~plAnimDebugList() {}
void AddObjects(char *subString);
void RemoveObjects(char *subString);
void ShowReport();
};
#endif

View File

@ -0,0 +1,224 @@
/*==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 "plBlower.h"
#include "plgDispatch.h"
#include "hsFastMath.h"
#include "../pnSceneObject/plSceneObject.h"
#include "../pnSceneObject/plCoordinateInterface.h"
#include "../pnMessage/plTimeMsg.h"
#include "hsTimer.h"
plRandom plBlower::fRandom;
static const hsScalar kDefaultMasterPower = 20.f;
static const hsScalar kDefaultMasterFrequency = 2.f;
static const hsScalar kDefaultDirectRate = 1.f;
static const hsScalar kDefaultImpulseRate = 1.e2f;
static const hsScalar kDefaultSpringKonst = 20.f;
static const hsScalar kDefaultBias = 0.25f;
static const hsScalar kInitialMaxOffDist = 1.f;
plBlower::plBlower()
:
fMasterPower(kDefaultMasterPower),
fMasterFrequency(kDefaultMasterFrequency),
fDirectRate(kDefaultDirectRate),
fImpulseRate(kDefaultImpulseRate),
fSpringKonst(kDefaultSpringKonst),
fBias(kDefaultBias),
fMaxOffsetDist(kInitialMaxOffDist),
fAccumTime(0)
{
fRestPos.Set(0,0,0);
fLocalRestPos.Set(0,0,0);
fCurrDel.Set(0,0,0);
fDirection.Set(fRandom.RandMinusOneToOne(), fRandom.RandMinusOneToOne(), 0);
hsFastMath::NormalizeAppr(fDirection);
}
plBlower::~plBlower()
{
}
void plBlower::IBlow(double secs, hsScalar delSecs)
{
hsPoint3 worldPos = fTarget->GetLocalToWorld().GetTranslate();
hsPoint3 localPos = fTarget->GetLocalToParent().GetTranslate();
// fast oscillation vs slow
// Completely random walk in the rotation
// Strength = Strength + rnd01 * (MaxStrength - Strength)
hsScalar t = (fAccumTime += delSecs);
hsScalar strength = 0;
int i;
for( i = 0; i < fOscillators.GetCount(); i++ )
{
hsScalar c, s;
t *= fOscillators[i].fFrequency * fMasterFrequency;
t += fOscillators[i].fPhase;
hsFastMath::SinCosAppr(t, s, c);
c += fBias;
strength += c * fOscillators[i].fPower;
}
strength *= fMasterPower;
if( strength < 0 )
strength = 0;
fDirection.fX += fRandom.RandMinusOneToOne() * delSecs * fDirectRate;
fDirection.fY += fRandom.RandMinusOneToOne() * delSecs * fDirectRate;
hsFastMath::NormalizeAppr(fDirection);
hsScalar offDist = hsVector3(&fRestPos, &worldPos).Magnitude();
if( offDist > fMaxOffsetDist )
fMaxOffsetDist = offDist;
hsVector3 force = fDirection * strength;
static hsScalar kOffsetDistFrac = 0.5f; // make me const
if( offDist > fMaxOffsetDist * kOffsetDistFrac )
{
offDist /= fMaxOffsetDist;
offDist *= fMasterPower;
hsScalar impulse = offDist * delSecs * fImpulseRate;
force.fX += impulse * fRandom.RandMinusOneToOne();
force.fY += impulse * fRandom.RandMinusOneToOne();
force.fZ += impulse * fRandom.RandMinusOneToOne();
}
const hsScalar kOffsetDistDecay = 0.999f;
fMaxOffsetDist *= kOffsetDistDecay;
hsVector3 accel = force;
accel += fSpringKonst * hsVector3(&fLocalRestPos, &localPos);
hsVector3 del = accel * (delSecs * delSecs);
fCurrDel = del;
}
hsBool plBlower::IEval(double secs, hsScalar delSecs, UInt32 dirty)
{
const hsScalar kMaxDelSecs = 0.1f;
if( delSecs > kMaxDelSecs )
delSecs = kMaxDelSecs;
IBlow(secs, delSecs);
ISetTargetTransform();
return true;
}
void plBlower::ISetTargetTransform()
{
plCoordinateInterface* ci = IGetTargetCoordinateInterface(0);
if( ci )
{
hsMatrix44 l2p = ci->GetLocalToParent();
hsMatrix44 p2l = ci->GetParentToLocal();
hsPoint3 pos = l2p.GetTranslate();
pos += fCurrDel;
l2p.SetTranslate(&pos);
p2l.SetTranslate(&-pos);
ci->SetLocalToParent(l2p, p2l);
}
}
void plBlower::SetTarget(plSceneObject* so)
{
plSingleModifier::SetTarget(so);
if( fTarget )
{
fRestPos = fTarget->GetLocalToWorld().GetTranslate();
fLocalRestPos = fTarget->GetLocalToParent().GetTranslate();
plgDispatch::Dispatch()->RegisterForExactType(plEvalMsg::Index(), GetKey());
}
IInitOscillators();
}
void plBlower::Read(hsStream* s, hsResMgr* mgr)
{
plSingleModifier::Read(s, mgr);
fMasterPower = s->ReadSwapScalar();
fDirectRate = s->ReadSwapScalar();
fImpulseRate = s->ReadSwapScalar();
fSpringKonst = s->ReadSwapScalar();
}
void plBlower::Write(hsStream* s, hsResMgr* mgr)
{
plSingleModifier::Write(s, mgr);
s->WriteSwapScalar(fMasterPower);
s->WriteSwapScalar(fDirectRate);
s->WriteSwapScalar(fImpulseRate);
s->WriteSwapScalar(fSpringKonst);
}
void plBlower::IInitOscillators()
{
const hsScalar kBasePower = 5.f;
fOscillators.SetCount(5);
int i;
for( i = 0; i < fOscillators.GetCount(); i++ )
{
hsScalar fi = hsScalar(i+1);
fOscillators[i].fFrequency = fi / hsScalarPI * fRandom.RandRangeF(0.75f, 1.25f);
// fOscillators[i].fFrequency = 1.f / hsScalarPI * fRandom.RandRangeF(0.5f, 1.5f);
fOscillators[i].fPhase = fRandom.RandZeroToOne();
fOscillators[i].fPower = kBasePower * fRandom.RandRangeF(0.75f, 1.25f);
}
}
void plBlower::SetConstancy(hsScalar f)
{
if( f < 0 )
f = 0;
else if( f > 1.f )
f = 1.f;
fBias = f;
}
hsScalar plBlower::GetConstancy() const
{
return fBias;
}

View File

@ -0,0 +1,101 @@
/*==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 plBlower_inc
#define plBlower_inc
#include "../pnModifier/plSingleModifier.h"
#include "hsGeometry3.h"
#include "../plMath/plRandom.h"
#include "hsTemplates.h"
class plSceneObject;
class hsStream;
class hsResMgr;
class plBlower : public plSingleModifier
{
protected:
class Oscillator
{
public:
hsScalar fFrequency;
hsScalar fPhase;
hsScalar fPower;
};
static plRandom fRandom;
// Parameters
hsScalar fMasterPower;
hsScalar fMasterFrequency;
hsScalar fDirectRate;
hsScalar fImpulseRate;
hsScalar fSpringKonst;
hsScalar fBias;
hsScalar fAccumTime;
hsTArray<Oscillator> fOscillators;
// CurrentState
hsVector3 fDirection;
hsPoint3 fRestPos;
hsPoint3 fLocalRestPos;
hsVector3 fCurrDel;
hsScalar fMaxOffsetDist;
void IInitOscillators();
void ISetTargetTransform();
void IBlow(double secs, hsScalar delSecs);
virtual hsBool IEval(double secs, hsScalar del, UInt32 dirty);
public:
~plBlower();
plBlower();
CLASSNAME_REGISTER( plBlower );
GETINTERFACE_ANY( plBlower, plSingleModifier );
virtual void SetTarget(plSceneObject* so);
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
void SetMasterPower(hsScalar f) { fMasterPower = f; }
void SetMasterFrequency(hsScalar f) { fMasterFrequency = f; }
void SetDirectRate(hsScalar f) { fDirectRate = f; }
void SetImpulseRate(hsScalar f) { fImpulseRate = f; }
void SetSpringKonst(hsScalar f) { fSpringKonst = f; }
void SetConstancy(hsScalar f);
hsScalar GetMasterPower() const { return fMasterPower; }
hsScalar GetMasterFrequency() const { return fMasterFrequency; }
hsScalar GetDirectRate() const { return fDirectRate; }
hsScalar GetImpulseRate() const { return fImpulseRate; }
hsScalar GetSpringKonst() const { return fSpringKonst; }
hsScalar GetConstancy() const;
};
#endif // plBlower_inc

View File

@ -0,0 +1,133 @@
/*==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 "plFilterCoordInterface.h"
#include "hsMatrix44.h"
#include "hsStream.h"
static hsMatrix44* InvTRS(const hsMatrix44& trs, hsMatrix44& inv)
{
inv.NotIdentity();
hsScalar invSSq[3];
invSSq[0] = 1.f / (trs.fMap[0][0] * trs.fMap[0][0] + trs.fMap[1][0] * trs.fMap[1][0] + trs.fMap[2][0] * trs.fMap[2][0]);
invSSq[1] = 1.f / (trs.fMap[0][1] * trs.fMap[0][1] + trs.fMap[1][1] * trs.fMap[1][1] + trs.fMap[2][1] * trs.fMap[2][1]);
invSSq[2] = 1.f / (trs.fMap[0][2] * trs.fMap[0][2] + trs.fMap[1][2] * trs.fMap[1][2] + trs.fMap[2][2] * trs.fMap[2][2]);
inv.fMap[0][0] = invSSq[0] * trs.fMap[0][0];
inv.fMap[0][1] = invSSq[0] * trs.fMap[1][0];
inv.fMap[0][2] = invSSq[0] * trs.fMap[2][0];
inv.fMap[0][3] = -(inv.fMap[0][0] * trs.fMap[0][3] + inv.fMap[0][1] * trs.fMap[1][3] + inv.fMap[0][2] * trs.fMap[2][3]);
inv.fMap[1][0] = invSSq[1] * trs.fMap[0][1];
inv.fMap[1][1] = invSSq[1] * trs.fMap[1][1];
inv.fMap[1][2] = invSSq[1] * trs.fMap[2][1];
inv.fMap[1][3] = -(inv.fMap[1][0] * trs.fMap[0][3] + inv.fMap[1][1] * trs.fMap[1][3] + inv.fMap[1][2] * trs.fMap[2][3]);
inv.fMap[2][0] = invSSq[2] * trs.fMap[0][2];
inv.fMap[2][1] = invSSq[2] * trs.fMap[1][2];
inv.fMap[2][2] = invSSq[2] * trs.fMap[2][2];
inv.fMap[2][3] = -(inv.fMap[2][0] * trs.fMap[0][3] + inv.fMap[2][1] * trs.fMap[1][3] + inv.fMap[2][2] * trs.fMap[2][3]);
inv.fMap[3][0] = inv.fMap[3][1] = inv.fMap[3][2] = 0;
inv.fMap[3][3] = 1.f;
return &inv;
}
plFilterCoordInterface::plFilterCoordInterface()
: fFilterMask(kNoRotation)
{
fRefParentLocalToWorld.Reset();
}
plFilterCoordInterface::~plFilterCoordInterface()
{
}
void plFilterCoordInterface::Read(hsStream* stream, hsResMgr* mgr)
{
plCoordinateInterface::Read(stream, mgr);
fFilterMask = stream->ReadSwap32();
fRefParentLocalToWorld.Read(stream);
}
void plFilterCoordInterface::Write(hsStream* stream, hsResMgr* mgr)
{
plCoordinateInterface::Write(stream, mgr);
stream->WriteSwap32(fFilterMask);
fRefParentLocalToWorld.Write(stream);
}
void plFilterCoordInterface::IRecalcTransforms()
{
if( !(fFilterMask && fParent) )
{
plCoordinateInterface::IRecalcTransforms();
return;
}
hsMatrix44 origL2W = fRefParentLocalToWorld * fLocalToParent;
fLocalToWorld = fParent->GetLocalToWorld() * fLocalToParent;
// Filter out the stuff we're discarding. Nothing fancy here,
// we're taking the simple (and fast) form and just stuffing in
// what we want to preserve based on our reference matrix.
if( fFilterMask & kNoTransX )
{
fLocalToWorld.fMap[0][3] = origL2W.fMap[0][3];
}
if( fFilterMask & kNoTransY )
{
fLocalToWorld.fMap[1][3] = origL2W.fMap[1][3];
}
if( fFilterMask & kNoTransZ )
{
fLocalToWorld.fMap[2][3] = origL2W.fMap[2][3];
}
if( fFilterMask & kNoRotation )
{
int i;
for( i = 0; i < 3; i++ )
{
int j;
for( j = 0; j < 3; j++ )
{
fLocalToWorld.fMap[i][j] = origL2W.fMap[i][j];
}
}
}
// Construct the inverse of local to world for world to local.
InvTRS(fLocalToWorld, fWorldToLocal);
}

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 plFilterCoordInterface_inc
#define plFilterCoordInterface_inc
#include "../pnSceneObject/plCoordinateInterface.h"
class plFilterCoordInterface : public plCoordinateInterface
{
public:
enum
{
kNoRotation = 0x1,
kNoTransX = 0x2,
kNoTransY = 0x4,
kNoTransZ = 0x8,
kNoMove = kNoTransX | kNoTransY | kNoTransZ,
kNoNothing = kNoRotation | kNoMove
};
protected:
UInt32 fFilterMask;
hsMatrix44 fRefParentLocalToWorld;
virtual void IRecalcTransforms();
public:
plFilterCoordInterface();
~plFilterCoordInterface();
CLASSNAME_REGISTER( plFilterCoordInterface );
GETINTERFACE_ANY( plFilterCoordInterface, plCoordinateInterface );
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
void SetFilterMask(UInt32 f) { fFilterMask = f; }
UInt32 GetFilterMask() const { return fFilterMask; }
void SetRefLocalToWorld(const hsMatrix44& m) { fRefParentLocalToWorld = m; }
const hsMatrix44& GetRefLocalToWorld() const { return fRefParentLocalToWorld; }
};
#endif // plFilterCoordInterface_inc

View File

@ -0,0 +1,282 @@
/*==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 "plFollowMod.h"
#include "plgDispatch.h"
#include "../pnNetCommon/plNetApp.h"
#include "../plMessage/plListenerMsg.h"
#include "../plMessage/plRenderMsg.h"
#include "../pnMessage/plTimeMsg.h"
#include "../pnSceneObject/plSceneObject.h"
#include "../pnMessage/plRefMsg.h"
#include "hsResMgr.h"
#include "plPipeline.h"
plFollowMod::plFollowMod()
: fLeader(nil), fMode(kPosition), fLeaderType(kLocalPlayer), fLeaderSet(false)
{
}
plFollowMod::~plFollowMod()
{
}
#include "plProfile.h"
plProfile_CreateTimer("FollowMod", "RenderSetup", FollowMod);
hsBool plFollowMod::MsgReceive(plMessage* msg)
{
plRenderMsg* rend = plRenderMsg::ConvertNoRef(msg);
if( rend )
{
plProfile_BeginLap(FollowMod, this->GetKey()->GetUoid().GetObjectName());
fLeaderL2W = rend->Pipeline()->GetCameraToWorld();
fLeaderW2L = rend->Pipeline()->GetWorldToCamera();
fLeaderSet = true;
plProfile_EndLap(FollowMod, this->GetKey()->GetUoid().GetObjectName());
return true;
}
plListenerMsg* list = plListenerMsg::ConvertNoRef(msg);
if( list )
{
hsVector3 pos;
pos.Set(list->GetPosition().fX, list->GetPosition().fY, list->GetPosition().fZ);
fLeaderL2W.MakeTranslateMat(&pos);
fLeaderW2L.MakeTranslateMat(&-pos);
fLeaderSet = true;
return true;
}
plGenRefMsg* ref = plGenRefMsg::ConvertNoRef(msg);
if( ref )
{
switch( ref->fType )
{
case kRefLeader:
if( ref->GetContext() & (plRefMsg::kOnCreate|plRefMsg::kOnRequest|plRefMsg::kOnReplace) )
fLeader = plSceneObject::ConvertNoRef(ref->GetRef());
else if( ref->GetContext() & (plRefMsg::kOnDestroy|plRefMsg::kOnRemove) )
fLeader = nil;
return true;
default:
hsAssert(false, "Unknown ref type to FollowMod");
break;
}
}
return plSingleModifier::MsgReceive(msg);
}
hsBool plFollowMod::ICheckLeader()
{
switch( fLeaderType )
{
case kLocalPlayer:
{
plSceneObject* player = plSceneObject::ConvertNoRef(plNetClientApp::GetInstance()->GetLocalPlayer());
if( player )
{
fLeaderL2W = player->GetLocalToWorld();
fLeaderW2L = player->GetWorldToLocal();
fLeaderSet = true;
}
else
fLeaderSet = false;
}
break;
case kObject:
if( fLeader )
{
fLeaderL2W = fLeader->GetLocalToWorld();
fLeaderW2L = fLeader->GetWorldToLocal();
fLeaderSet = true;
}
else
fLeaderSet = false;
break;
case kCamera:
break;
case kListener:
break;
}
return fLeaderSet;
}
void plFollowMod::IMoveTarget()
{
if( fMode == kFullTransform )
{
GetTarget()->SetTransform(fLeaderL2W, fLeaderW2L);
return;
}
hsMatrix44 l2w = GetTarget()->GetLocalToWorld();
hsMatrix44 w2l = GetTarget()->GetWorldToLocal();
if( fMode & kRotate )
{
int i, j;
for( i = 0; i < 3; i++ )
{
for( j = 0; j < 3; j++ )
{
l2w.fMap[i][j] = fLeaderL2W.fMap[i][j];
w2l.fMap[i][j] = fLeaderW2L.fMap[i][j];
}
}
}
if( fMode & kPosition )
{
hsMatrix44 invMove;
invMove.Reset();
hsPoint3 newPos = fLeaderL2W.GetTranslate();
hsPoint3 newInvPos = fLeaderW2L.GetTranslate();
hsPoint3 oldPos = l2w.GetTranslate();
// l2w = newPosMat * -oldPosMat * l2w
// so w2l = w2l * inv-oldPosMat * invNewPosMat
if( fMode & kPositionX )
{
l2w.fMap[0][3] = newPos.fX;
invMove.fMap[0][3] = oldPos.fX - newPos.fX;
}
if( fMode & kPositionY )
{
l2w.fMap[1][3] = newPos.fY;
invMove.fMap[1][3] = oldPos.fY - newPos.fY;
}
if( fMode & kPositionZ )
{
l2w.fMap[2][3] = newPos.fZ;
invMove.fMap[2][3] = oldPos.fZ - newPos.fZ;
}
invMove.NotIdentity();
// InvMove must happen after rotation.
w2l = w2l * invMove;
}
l2w.NotIdentity();
w2l.NotIdentity();
#ifdef HS_DEBUGGING
//MFHORSE hackola
hsMatrix44 inv;
l2w.GetInverse(&inv);
#endif // HS_DEBUGGING
GetTarget()->SetTransform(l2w, w2l);
}
hsBool plFollowMod::IEval(double secs, hsScalar del, UInt32 dirty)
{
if( ICheckLeader() )
IMoveTarget();
return true;
}
void plFollowMod::SetTarget(plSceneObject* so)
{
plSingleModifier::SetTarget(so);
if( fTarget )
Activate();
else
Deactivate();
}
void plFollowMod::Activate()
{
switch( fLeaderType )
{
case kLocalPlayer:
break;
case kObject:
break;
case kCamera:
plgDispatch::Dispatch()->RegisterForExactType(plRenderMsg::Index(), GetKey());
break;
case kListener:
plgDispatch::Dispatch()->RegisterForExactType(plListenerMsg::Index(), GetKey());
break;
}
if( fTarget )
plgDispatch::Dispatch()->RegisterForExactType(plEvalMsg::Index(), GetKey());
}
void plFollowMod::Deactivate()
{
switch( fLeaderType )
{
case kLocalPlayer:
if( fTarget )
plgDispatch::Dispatch()->UnRegisterForExactType(plEvalMsg::Index(), GetKey());
break;
case kObject:
if( fTarget )
plgDispatch::Dispatch()->UnRegisterForExactType(plEvalMsg::Index(), GetKey());
break;
case kCamera:
plgDispatch::Dispatch()->UnRegisterForExactType(plRenderMsg::Index(), GetKey());
break;
case kListener:
plgDispatch::Dispatch()->UnRegisterForExactType(plListenerMsg::Index(), GetKey());
break;
}
}
void plFollowMod::Read(hsStream* stream, hsResMgr* mgr)
{
plSingleModifier::Read(stream, mgr);
fLeaderType = FollowLeaderType(stream->ReadByte());
fMode = stream->ReadByte();
mgr->ReadKeyNotifyMe(stream, TRACKED_NEW plGenRefMsg(GetKey(), plRefMsg::kOnCreate, 0, kRefLeader), plRefFlags::kActiveRef);
// If active?
Activate();
}
void plFollowMod::Write(hsStream* stream, hsResMgr* mgr)
{
plSingleModifier::Write(stream, mgr);
stream->WriteByte(fLeaderType);
stream->WriteByte(fMode);
mgr->WriteKey(stream, fLeader);
}

View File

@ -0,0 +1,101 @@
/*==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 plFollowMod_inc
#define plFollowMod_inc
#include "hsMatrix44.h"
#include "../pnModifier/plSingleModifier.h"
class plSceneObject;
class plMessage;
class hsStream;
class hsResMgr;
class plFollowMod : public plSingleModifier
{
public:
enum FollowRefs
{
kRefLeader
};
enum FollowLeaderType
{
kLocalPlayer,
kObject,
kCamera,
kListener
};
enum FollowModMode
{
kPositionX = 0x1,
kPositionY = 0x2,
kPositionZ = 0x4,
kPosition = (kPositionX | kPositionY | kPositionZ),
kRotate = 0x8,
kFullTransform = kPosition | kRotate
};
protected:
FollowLeaderType fLeaderType;
UInt8 fMode;
UInt8 fLeaderSet;
plSceneObject* fLeader; // may be nil if Leader isn't a sceneobject
hsMatrix44 fLeaderL2W;
hsMatrix44 fLeaderW2L;
hsBool ICheckLeader();
void IMoveTarget();
virtual hsBool IEval(double secs, hsScalar del, UInt32 dirty);
public:
plFollowMod();
~plFollowMod();
CLASSNAME_REGISTER( plFollowMod );
GETINTERFACE_ANY( plFollowMod, 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);
void SetType(FollowLeaderType t) { fLeaderType = t; }
FollowLeaderType GetType() const { return fLeaderType; }
void SetMode(UInt8 m) { fMode = m; }
UInt8 GetMode() const { return fMode; }
void Activate();
void Deactivate();
};
#endif // plFollowMod_inc

View File

@ -0,0 +1,413 @@
/*==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 "plLightModifier.h"
#include "../plGLight/plLightInfo.h"
#include "../plInterp/plController.h"
#include "hsStream.h"
#include "hsResMgr.h"
////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////
// Basic light
plLightModifier::plLightModifier()
: fLight(nil),
fColorCtl(nil),
fAmbientCtl(nil),
fSpecularCtl(nil)
{
}
plLightModifier::~plLightModifier()
{
delete fColorCtl;
fColorCtl = nil;
delete fAmbientCtl;
fAmbientCtl = nil;
delete fSpecularCtl;
fSpecularCtl = nil;
}
void plLightModifier::IClearCtls()
{
delete fColorCtl;
fColorCtl = nil;
delete fAmbientCtl;
fAmbientCtl = nil;
delete fSpecularCtl;
fSpecularCtl = nil;
}
void plLightModifier::AddTarget(plSceneObject* so)
{
plSimpleModifier::AddTarget(so);
if( so )
fLight = plLightInfo::ConvertNoRef(so->GetGenericInterface(plLightInfo::Index()));
else
fLight = nil;
}
void plLightModifier::RemoveTarget(plSceneObject* so)
{
if( so = fTarget )
fLight = nil;
plSimpleModifier::RemoveTarget(so);
}
void plLightModifier::Read(hsStream* s, hsResMgr* mgr)
{
plSimpleModifier::Read(s, mgr);
fColorCtl = plController::ConvertNoRef(mgr->ReadCreatable(s));
fAmbientCtl = plController::ConvertNoRef(mgr->ReadCreatable(s));
fSpecularCtl = plController::ConvertNoRef(mgr->ReadCreatable(s));
}
void plLightModifier::Write(hsStream* s, hsResMgr* mgr)
{
plSimpleModifier::Write(s, mgr);
mgr->WriteCreatable(s, fColorCtl);
mgr->WriteCreatable(s, fAmbientCtl);
mgr->WriteCreatable(s, fSpecularCtl);
}
void plLightModifier::IApplyDynamic()
{
hsColorRGBA col;
if( fLight != nil )
{
if( fColorCtl )
{
col.Set(0,0,0,1.f);
fColorCtl->Interp(fCurrentTime, &col);
fLight->SetDiffuse(col);
}
if( fAmbientCtl )
{
col.Set(0,0,0,1.f);
fAmbientCtl->Interp(fCurrentTime, &col);
fLight->SetAmbient(col);
}
if( fSpecularCtl )
{
col.Set(0,0,0,1.f);
fSpecularCtl->Interp(fCurrentTime, &col);
fLight->SetSpecular(col);
}
}
}
void plLightModifier::DefaultAnimation()
{
hsScalar len = MaxAnimLength(0);
fTimeConvert.SetBegin(0);
fTimeConvert.SetEnd(len);
fTimeConvert.SetLoopPoints(0, len);
fTimeConvert.Loop();
fTimeConvert.Start();
}
hsScalar plLightModifier::MaxAnimLength(hsScalar len) const
{
if( fColorCtl && (fColorCtl->GetLength() > len) )
len = fColorCtl->GetLength();
if( fAmbientCtl && (fAmbientCtl->GetLength() > len) )
len = fAmbientCtl->GetLength();
if( fSpecularCtl && (fSpecularCtl->GetLength() > len) )
len = fSpecularCtl->GetLength();
return len;
}
////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////
// Omni Lights
plOmniModifier::plOmniModifier()
: fOmni(nil),
fAttenCtl(nil)
{
}
plOmniModifier::~plOmniModifier()
{
delete fAttenCtl;
fAttenCtl = nil;
}
void plOmniModifier::AddTarget(plSceneObject* so)
{
plLightModifier::AddTarget(so);
if( fLight )
fOmni = plOmniLightInfo::ConvertNoRef(fLight);
else
fOmni = nil;
}
void plOmniModifier::RemoveTarget(plSceneObject* so)
{
plLightModifier::RemoveTarget(so);
if( !fLight )
fOmni = nil;
}
void plOmniModifier::IClearCtls()
{
plLightModifier::IClearCtls();
delete fAttenCtl;
fAttenCtl = nil;
}
void plOmniModifier::Read(hsStream* s, hsResMgr* mgr)
{
plLightModifier::Read(s, mgr);
fAttenCtl = plController::ConvertNoRef(mgr->ReadCreatable(s));
fInitAtten.Read(s);
}
void plOmniModifier::Write(hsStream* s, hsResMgr* mgr)
{
plLightModifier::Write(s, mgr);
mgr->WriteCreatable(s, fAttenCtl);
fInitAtten.Write(s);
}
void plOmniModifier::IApplyDynamic()
{
plLightModifier::IApplyDynamic();
if( fAttenCtl )
{
hsPoint3 p = fInitAtten;
fAttenCtl->Interp(fCurrentTime, &p);
fOmni->SetConstantAttenuation(p.fX);
fOmni->SetLinearAttenuation(p.fY);
fOmni->SetQuadraticAttenuation(p.fZ);
}
}
hsScalar plOmniModifier::MaxAnimLength(hsScalar len) const
{
len = plLightModifier::MaxAnimLength(len);
if( fAttenCtl && (fAttenCtl->GetLength() > len) )
len = fAttenCtl->GetLength();
return len;
}
////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////
// Spot Lights
plSpotModifier::plSpotModifier()
: fSpot(nil),
fInnerCtl(nil),
fOuterCtl(nil)
{
}
plSpotModifier::~plSpotModifier()
{
delete fInnerCtl;
fInnerCtl = nil;
delete fOuterCtl;
fOuterCtl = nil;
}
void plSpotModifier::AddTarget(plSceneObject* so)
{
plOmniModifier::AddTarget(so);
if( fLight )
fSpot = plSpotLightInfo::ConvertNoRef(fLight);
else
fSpot = nil;
}
void plSpotModifier::RemoveTarget(plSceneObject* so)
{
plOmniModifier::RemoveTarget(so);
if( !fLight )
fSpot = nil;
}
void plSpotModifier::IClearCtls()
{
plOmniModifier::IClearCtls();
delete fInnerCtl;
fInnerCtl = nil;
delete fOuterCtl;
fOuterCtl = nil;
}
void plSpotModifier::Read(hsStream* s, hsResMgr* mgr)
{
plOmniModifier::Read(s, mgr);
fInnerCtl = plController::ConvertNoRef(mgr->ReadCreatable(s));
fOuterCtl = plController::ConvertNoRef(mgr->ReadCreatable(s));
}
void plSpotModifier::Write(hsStream* s, hsResMgr* mgr)
{
plOmniModifier::Write(s, mgr);
mgr->WriteCreatable(s, fInnerCtl);
mgr->WriteCreatable(s, fOuterCtl);
}
void plSpotModifier::IApplyDynamic()
{
plOmniModifier::IApplyDynamic();
hsScalar f;
if( fInnerCtl )
{
fInnerCtl->Interp(fCurrentTime, &f);
fSpot->SetSpotInner(hsScalarDegToRad(f)*0.5f);
}
if( fOuterCtl )
{
fOuterCtl->Interp(fCurrentTime, &f);
fSpot->SetSpotOuter(hsScalarDegToRad(f)*0.5f);
}
}
hsScalar plSpotModifier::MaxAnimLength(hsScalar len) const
{
len = plOmniModifier::MaxAnimLength(len);
if( fInnerCtl && (fInnerCtl->GetLength() > len) )
len = fInnerCtl->GetLength();
if( fOuterCtl && (fOuterCtl->GetLength() > len) )
len = fOuterCtl->GetLength();
return len;
}
////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////
// LtdDir Lights
plLtdDirModifier::plLtdDirModifier()
: fLtdDir(nil),
fWidthCtl(nil),
fHeightCtl(nil),
fDepthCtl(nil)
{
}
plLtdDirModifier::~plLtdDirModifier()
{
delete fWidthCtl;
fWidthCtl = nil;
delete fHeightCtl;
fHeightCtl = nil;
delete fDepthCtl;
fDepthCtl = nil;
}
void plLtdDirModifier::AddTarget(plSceneObject* so)
{
plLightModifier::AddTarget(so);
if( fLight )
fLtdDir = plLimitedDirLightInfo::ConvertNoRef(fLight);
else
fLtdDir = nil;
}
void plLtdDirModifier::RemoveTarget(plSceneObject* so)
{
plLightModifier::RemoveTarget(so);
if( !fLight )
fLtdDir = nil;
}
void plLtdDirModifier::IClearCtls()
{
plLightModifier::IClearCtls();
delete fWidthCtl;
fWidthCtl = nil;
delete fHeightCtl;
fHeightCtl = nil;
delete fDepthCtl;
fDepthCtl = nil;
}
void plLtdDirModifier::Read(hsStream* s, hsResMgr* mgr)
{
plLightModifier::Read(s, mgr);
fWidthCtl = plController::ConvertNoRef(mgr->ReadCreatable(s));
fHeightCtl = plController::ConvertNoRef(mgr->ReadCreatable(s));
fDepthCtl = plController::ConvertNoRef(mgr->ReadCreatable(s));
}
void plLtdDirModifier::Write(hsStream* s, hsResMgr* mgr)
{
plLightModifier::Write(s, mgr);
mgr->WriteCreatable(s, fWidthCtl);
mgr->WriteCreatable(s, fHeightCtl);
mgr->WriteCreatable(s, fDepthCtl);
}
void plLtdDirModifier::IApplyDynamic()
{
plLightModifier::IApplyDynamic();
hsScalar f;
if( fWidthCtl )
{
fWidthCtl->Interp(fCurrentTime, &f);
fLtdDir->SetWidth(f);
}
if( fHeightCtl )
{
fHeightCtl->Interp(fCurrentTime, &f);
fLtdDir->SetHeight(f);
}
if( fDepthCtl )
{
fDepthCtl->Interp(fCurrentTime, &f);
fLtdDir->SetDepth(f);
}
}
hsScalar plLtdDirModifier::MaxAnimLength(hsScalar len) const
{
len = plLightModifier::MaxAnimLength(len);
if( fWidthCtl && (fWidthCtl->GetLength() > len) )
len = fWidthCtl->GetLength();
if( fHeightCtl && (fHeightCtl->GetLength() > len) )
len = fHeightCtl->GetLength();
if( fDepthCtl && (fDepthCtl->GetLength() > len) )
len = fDepthCtl->GetLength();
return len;
}

View File

@ -0,0 +1,181 @@
/*==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 plLightModifier_inc
#define plLightModifier_inc
#include "../../PubUtilLib/plModifier/plSimpleModifier.h"
#include "hsGeometry3.h"
class plController;
class plController;
class plLightInfo;
class plOmniLightInfo;
class plSpotLightInfo;
class plLimitedDirLightInfo;
class plLightModifier : public plSimpleModifier
{
protected:
plController* fColorCtl;
plController* fAmbientCtl;
plController* fSpecularCtl;
plLightInfo* fLight;
virtual void IApplyDynamic();
virtual void IClearCtls();
public:
plLightModifier();
virtual ~plLightModifier();
CLASSNAME_REGISTER( plLightModifier );
GETINTERFACE_ANY( plLightModifier, plSimpleModifier );
virtual void AddTarget(plSceneObject* so);
virtual void RemoveTarget(plSceneObject* so);
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
virtual hsBool HasAnima() const { return fColorCtl || fAmbientCtl || fSpecularCtl; }
// Export only
void SetColorCtl(plController* ctl) { fColorCtl = ctl; }
void SetAmbientCtl(plController* ctl) { fAmbientCtl = ctl; }
void SetSpecularCtl(plController* ctl) { fSpecularCtl = ctl; }
virtual void DefaultAnimation();
virtual hsScalar MaxAnimLength(hsScalar len) const;
};
class plOmniModifier : public plLightModifier
{
protected:
plOmniLightInfo* fOmni;
plController* fAttenCtl;
hsPoint3 fInitAtten;
virtual void IApplyDynamic();
virtual void IClearCtls();
public:
plOmniModifier();
virtual ~plOmniModifier();
CLASSNAME_REGISTER( plOmniModifier );
GETINTERFACE_ANY( plOmniModifier, plLightModifier );
virtual void AddTarget(plSceneObject* so);
virtual void RemoveTarget(plSceneObject* so);
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
virtual hsBool HasAnima() const { return plLightModifier::HasAnima() || fAttenCtl; }
// Export Only
void SetAttenCtl(plController* ctl) { fAttenCtl = ctl; }
void SetInitAtten(const hsPoint3& p) { fInitAtten = p; }
virtual hsScalar MaxAnimLength(hsScalar len) const;
};
class plSpotModifier : public plOmniModifier
{
protected:
plSpotLightInfo* fSpot;
plController* fInnerCtl;
plController* fOuterCtl;
virtual void IApplyDynamic();
virtual void IClearCtls();
public:
plSpotModifier();
virtual ~plSpotModifier();
CLASSNAME_REGISTER( plSpotModifier );
GETINTERFACE_ANY( plSpotModifier, plLightModifier );
virtual void AddTarget(plSceneObject* so);
virtual void RemoveTarget(plSceneObject* so);
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
virtual hsBool HasAnima() const { return plOmniModifier::HasAnima() || fInnerCtl || fOuterCtl; }
// Export Only
void SetInnerCtl(plController* ctl) { fInnerCtl = ctl; }
void SetOuterCtl(plController* ctl) { fOuterCtl = ctl; }
virtual hsScalar MaxAnimLength(hsScalar len) const;
};
class plLtdDirModifier : public plLightModifier
{
protected:
plLimitedDirLightInfo* fLtdDir;
plController* fWidthCtl;
plController* fHeightCtl;
plController* fDepthCtl;
virtual void IApplyDynamic();
virtual void IClearCtls();
public:
plLtdDirModifier();
virtual ~plLtdDirModifier();
CLASSNAME_REGISTER( plLtdDirModifier );
GETINTERFACE_ANY( plLtdDirModifier, plLightModifier );
virtual void AddTarget(plSceneObject* so);
virtual void RemoveTarget(plSceneObject* so);
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
virtual hsBool HasAnima() const { return plLightModifier::HasAnima() || fWidthCtl || fHeightCtl || fDepthCtl; }
// Export Only
void SetWidthCtl(plController* ctl) { fWidthCtl = ctl; }
void SetHeightCtl(plController* ctl) { fHeightCtl = ctl; }
void SetDepthCtl(plController* ctl) { fDepthCtl = ctl; }
virtual hsScalar MaxAnimLength(hsScalar len) const;
};
#endif // plLightModifier_inc

View File

@ -0,0 +1,687 @@
/*==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 "plLineFollowMod.h"
#include "plStereizer.h"
#include "../plInterp/plAnimPath.h"
#include "hsResMgr.h"
#include "../pnMessage/plRefMsg.h"
#include "../pnSceneObject/plSceneObject.h"
#include "../pnSceneObject/plCoordinateInterface.h"
#include "../pnSceneObject/plDrawInterface.h"
#include "plgDispatch.h"
#include "../plMessage/plListenerMsg.h"
#include "../plMessage/plRenderMsg.h"
#include "../pnMessage/plTimeMsg.h"
#include "hsBounds.h"
#include "plPipeline.h"
#include "hsFastMath.h"
#include "../pnMessage/plPlayerPageMsg.h"
#include "../pnNetCommon/plNetApp.h"
#include "../plNetClient/plNetClientMgr.h"
#include "hsTimer.h"
plLineFollowMod::plLineFollowMod()
: fPath(nil),
fPathParent(nil),
fRefObj(nil),
fFollowMode(kFollowListener),
fFollowFlags(kNone),
fOffset(0),
fOffsetClamp(0),
fSpeedClamp(0)
{
fSearchPos.Set(0,0,0);
}
plLineFollowMod::~plLineFollowMod()
{
delete fPath;
}
void plLineFollowMod::SetSpeedClamp(hsScalar fps)
{
fSpeedClamp = fps;
if( fSpeedClamp > 0 )
{
fFollowFlags |= kSpeedClamp;
}
else
{
fFollowFlags &= ~kSpeedClamp;
}
}
void plLineFollowMod::SetOffsetFeet(hsScalar f)
{
fOffset = f;
if( fOffset != 0 )
{
fFollowFlags &= ~kOffsetAng;
fFollowFlags |= kOffsetFeet;
}
else
{
fFollowFlags &= ~kOffset;
}
}
void plLineFollowMod::SetForceToLine(hsBool on)
{
if( on )
fFollowFlags |= kForceToLine;
else
fFollowFlags &= ~kForceToLine;
}
void plLineFollowMod::SetOffsetDegrees(hsScalar f)
{
fOffset = hsScalarDegToRad(f);
if( fOffset != 0 )
{
fFollowFlags &= ~kOffsetFeet;
fFollowFlags |= kOffsetAng;
fTanOffset = tanf(f);
}
else
{
fFollowFlags &= ~kOffset;
}
}
void plLineFollowMod::SetOffsetClamp(hsScalar f)
{
fOffsetClamp = f;
if( fOffsetClamp > 0 )
{
fFollowFlags |= kOffsetClamp;
}
else
{
fFollowFlags &= ~kOffsetClamp;
}
}
void plLineFollowMod::SetPath(plAnimPath* path)
{
delete fPath;
fPath = path;
}
void plLineFollowMod::Read(hsStream* stream, hsResMgr* mgr)
{
plMultiModifier::Read(stream, mgr);
fPath = plAnimPath::ConvertNoRef(mgr->ReadCreatable(stream));
mgr->ReadKeyNotifyMe(stream, TRACKED_NEW plGenRefMsg(GetKey(), plRefMsg::kOnCreate, 0, kRefParent), plRefFlags::kPassiveRef);
mgr->ReadKeyNotifyMe(stream, TRACKED_NEW plGenRefMsg(GetKey(), plRefMsg::kOnCreate, 0, kRefObject), plRefFlags::kPassiveRef);
int n = stream->ReadSwap32();
while(n--)
{
mgr->ReadKeyNotifyMe(stream, TRACKED_NEW plGenRefMsg(GetKey(), plRefMsg::kOnCreate, 0, kRefStereizer), plRefFlags::kPassiveRef);
}
UInt32 f = stream->ReadSwap32();
SetFollowMode(FollowMode(f & 0xffff));
fFollowFlags = (UInt16)((f >> 16) & 0xffff);
if( fFollowFlags & kOffset )
{
fOffset = stream->ReadSwapScalar();
}
if( fFollowFlags & kOffsetAng )
{
fTanOffset = tanf(fOffset);
}
if( fFollowFlags & kOffsetClamp )
{
fOffsetClamp = stream->ReadSwapScalar();
}
if( fFollowFlags & kSpeedClamp )
{
fSpeedClamp = stream->ReadSwapScalar();
}
}
void plLineFollowMod::Write(hsStream* stream, hsResMgr* mgr)
{
plMultiModifier::Write(stream, mgr);
mgr->WriteCreatable(stream, fPath);
mgr->WriteKey(stream, fPathParent);
mgr->WriteKey(stream, fRefObj);
stream->WriteSwap32(fStereizers.GetCount());
int i;
for( i = 0; i < fStereizers.GetCount(); i++ )
mgr->WriteKey(stream, fStereizers[i]->GetKey());
UInt32 f = UInt32(fFollowMode) | (UInt32(fFollowFlags) << 16);
stream->WriteSwap32(f);
if( fFollowFlags & kOffset )
stream->WriteSwapScalar(fOffset);
if( fFollowFlags & kOffsetClamp )
stream->WriteSwapScalar(fOffsetClamp);
if( fFollowFlags & kSpeedClamp )
stream->WriteSwapScalar(fSpeedClamp);
}
#include "plProfile.h"
plProfile_CreateTimer("LineFollow", "RenderSetup", LineFollow);
hsBool plLineFollowMod::MsgReceive(plMessage* msg)
{
plGenRefMsg* refMsg = plGenRefMsg::ConvertNoRef(msg);
if( refMsg )
{
if( refMsg->GetContext() & (plRefMsg::kOnCreate|plRefMsg::kOnRequest|plRefMsg::kOnReplace) )
{
plSceneObject* obj = plSceneObject::ConvertNoRef(refMsg->GetRef());
if( kRefParent == refMsg->fType )
fPathParent = obj;
else if( kRefObject == refMsg->fType )
fRefObj = obj;
else if( kRefStereizer == refMsg->fType )
{
plStereizer* ster = plStereizer::ConvertNoRef(refMsg->GetRef());
int idx = fStereizers.Find(ster);
if( idx == fStereizers.kMissingIndex )
fStereizers.Append(ster);
}
}
else if( refMsg->GetContext() & (plRefMsg::kOnDestroy|plRefMsg::kOnRemove) )
{
if( kRefParent == refMsg->fType )
fPathParent = nil;
else if( kRefObject == refMsg->fType )
fRefObj = nil;
else if( kRefStereizer == refMsg->fType )
{
plStereizer* ster = (plStereizer*)(refMsg->GetRef());
int idx = fStereizers.Find(ster);
if( idx != fStereizers.kMissingIndex )
fStereizers.Remove(idx);
}
}
return true;
}
plRenderMsg* rend = plRenderMsg::ConvertNoRef(msg);
if( rend )
{
plProfile_BeginLap(LineFollow, this->GetKey()->GetUoid().GetObjectName());
hsPoint3 oldPos = fSearchPos;
fSearchPos = rend->Pipeline()->GetViewPositionWorld();
ICheckForPop(oldPos, fSearchPos);
plProfile_EndLap(LineFollow, this->GetKey()->GetUoid().GetObjectName());
return true;
}
plListenerMsg* list = plListenerMsg::ConvertNoRef(msg);
if( list )
{
hsPoint3 oldPos = fSearchPos;
fSearchPos = list->GetPosition();
ICheckForPop(oldPos, fSearchPos);
ISetupStereizers(list);
return true;
}
plPlayerPageMsg* pPMsg = plPlayerPageMsg::ConvertNoRef(msg);
if (pPMsg)
{
if (pPMsg->fPlayer == plNetClientMgr::GetInstance()->GetLocalPlayerKey() && !pPMsg->fUnload)
{
fRefObj = (plSceneObject*)pPMsg->fPlayer->GetObjectPtr();
}
return true;
}
return plMultiModifier::MsgReceive(msg);
}
void plLineFollowMod::SetFollowMode(FollowMode f)
{
IUnRegister();
fFollowMode = f;
IRegister();
plgDispatch::Dispatch()->RegisterForExactType(plEvalMsg::Index(), GetKey());
}
void plLineFollowMod::IUnRegister()
{
switch( fFollowMode )
{
case kFollowObject:
break;
case kFollowListener:
plgDispatch::Dispatch()->UnRegisterForExactType(plListenerMsg::Index(), GetKey());
break;
case kFollowCamera:
plgDispatch::Dispatch()->UnRegisterForExactType(plRenderMsg::Index(), GetKey());
break;
case kFollowLocalAvatar:
plgDispatch::Dispatch()->UnRegisterForExactType(plPlayerPageMsg::Index(), GetKey());
break;
}
}
void plLineFollowMod::IRegister()
{
switch( fFollowMode )
{
case kFollowObject:
break;
case kFollowListener:
plgDispatch::Dispatch()->RegisterForExactType(plListenerMsg::Index(), GetKey());
break;
case kFollowCamera:
plgDispatch::Dispatch()->RegisterForExactType(plRenderMsg::Index(), GetKey());
break;
case kFollowLocalAvatar:
{
if (plNetClientApp::GetInstance() && plNetClientApp::GetInstance()->GetLocalPlayer())
fRefObj = ((plSceneObject*)plNetClientApp::GetInstance()->GetLocalPlayer());
plgDispatch::Dispatch()->RegisterForExactType(plPlayerPageMsg::Index(), GetKey());
break;
}
}
}
hsBool plLineFollowMod::IEval(double secs, hsScalar del, UInt32 dirty)
{
if( !fPath )
return false;
ISetPathTransform();
if( !IGetSearchPos() )
return false;
hsMatrix44 tgtXfm;
IGetTargetTransform(fSearchPos, tgtXfm);
if( fFollowFlags & kOffset )
IOffsetTargetTransform(tgtXfm);
int i;
for( i = 0; i < GetNumTargets(); i++ )
{
ISetTargetTransform(i, tgtXfm);
}
return true;
}
hsBool plLineFollowMod::IOffsetTargetTransform(hsMatrix44& tgtXfm)
{
hsPoint3 tgtPos = tgtXfm.GetTranslate();
hsVector3 tgt2src(&fSearchPos, &tgtPos);
hsScalar t2sLen = tgt2src.Magnitude();
hsFastMath::NormalizeAppr(tgt2src);
hsVector3 out;
out.Set(-tgt2src.fY, tgt2src.fX, 0); // (0,0,1) X (tgt2src)
if( fFollowFlags & kOffsetAng )
{
hsScalar del = t2sLen * fTanOffset;
if( fFollowFlags & kOffsetClamp )
{
if( del > fOffsetClamp )
del = fOffsetClamp;
else if( del < -fOffsetClamp )
del = -fOffsetClamp;
}
out *= del;
}
else if( fFollowFlags & kOffsetFeet )
{
out *= fOffset;
}
else
out.Set(0,0,0);
if( fFollowFlags & kForceToLine )
{
hsPoint3 newSearch = tgtPos;
newSearch += out;
IGetTargetTransform(newSearch, tgtXfm);
}
else
{
tgtXfm.fMap[0][3] += out[0];
tgtXfm.fMap[1][3] += out[1];
tgtXfm.fMap[2][3] += out[2];
}
return true;
}
hsBool plLineFollowMod::IGetTargetTransform(hsPoint3& searchPos, hsMatrix44& tgtXfm)
{
hsScalar t = fPath->GetExtremePoint(searchPos);
if( fFollowFlags & kFullMatrix )
{
fPath->SetCurTime(t, plAnimPath::kNone);
fPath->GetMatrix44(&tgtXfm);
}
else
{
fPath->SetCurTime(t, plAnimPath::kCalcPosOnly);
hsPoint3 pos;
fPath->GetPosition(&pos);
tgtXfm.MakeTranslateMat((hsVector3*)&pos);
}
return true;
}
void plLineFollowMod::ISetPathTransform()
{
if( fPathParent && fPathParent->GetCoordinateInterface() )
{
hsMatrix44 l2w = fPathParent->GetCoordinateInterface()->GetLocalToWorld();
hsMatrix44 w2l = fPathParent->GetCoordinateInterface()->GetWorldToLocal();
fPath->SetTransform(l2w, w2l);
}
}
void plLineFollowMod::ICheckForPop(const hsPoint3& oldPos, const hsPoint3& newPos)
{
hsVector3 del(&oldPos, &newPos);
hsScalar elapsed = hsTimer::GetDelSysSeconds();
hsScalar speedSq = 0.f;
if (elapsed > 0.f)
speedSq = del.MagnitudeSquared() / elapsed;
const hsScalar kMaxSpeedSq = 30.f * 30.f; // (feet per sec)^2
if( speedSq > kMaxSpeedSq )
fFollowFlags |= kSearchPosPop;
else
fFollowFlags &= ~kSearchPosPop;
}
hsBool plLineFollowMod::IGetSearchPos()
{
hsPoint3 oldPos = fSearchPos;
if( kFollowObject == fFollowMode )
{
if( !fRefObj )
return false;
if( fRefObj->GetCoordinateInterface() )
{
fSearchPos = fRefObj->GetCoordinateInterface()->GetWorldPos();
ICheckForPop(oldPos, fSearchPos);
return true;
}
else if( fRefObj->GetDrawInterface() )
{
fSearchPos = fRefObj->GetDrawInterface()->GetWorldBounds().GetCenter();
ICheckForPop(oldPos, fSearchPos);
return true;
}
return false;
}
else
if (fFollowMode == kFollowLocalAvatar)
{
if (!fRefObj)
return false;
if( fRefObj->GetCoordinateInterface() )
{
fSearchPos = fRefObj->GetCoordinateInterface()->GetWorldPos();
ICheckForPop(oldPos, fSearchPos);
return true;
}
else if( fRefObj->GetDrawInterface() )
{
fSearchPos = fRefObj->GetDrawInterface()->GetWorldBounds().GetCenter();
ICheckForPop(oldPos, fSearchPos);
return true;
}
return false;
}
return true;
}
hsMatrix44 plLineFollowMod::IInterpMatrices(const hsMatrix44& m0, const hsMatrix44& m1, hsScalar parm)
{
hsMatrix44 retVal;
int i, j;
for( i = 0; i < 3; i++ )
{
for( j = 0; j < 4; j++ )
{
retVal.fMap[i][j] = m0.fMap[i][j] * (1.f - parm) + m1.fMap[i][j] * parm;
}
}
retVal.fMap[3][0] = retVal.fMap[3][1] = retVal.fMap[3][2] = 0;
retVal.fMap[3][3] = 1.f;
retVal.NotIdentity();
return retVal;
}
hsMatrix44 plLineFollowMod::ISpeedClamp(plCoordinateInterface* ci, const hsMatrix44& unclTgtXfm)
{
// If our search position has popped, or delsysseconds is zero, just return as is.
if( (fFollowFlags & kSearchPosPop) || !(hsTimer::GetDelSysSeconds() > 0) )
return unclTgtXfm;
const hsMatrix44 currL2W = ci->GetLocalToWorld();
const hsPoint3 oldPos = currL2W.GetTranslate();
const hsPoint3 newPos = unclTgtXfm.GetTranslate();
const hsVector3 del(&newPos, &oldPos);
hsScalar elapsed = hsTimer::GetDelSysSeconds();
hsScalar speed = 0.f;
if (elapsed > 0.f)
speed = del.Magnitude() / elapsed;
if( speed > fSpeedClamp )
{
hsScalar parm = fSpeedClamp / speed;
hsMatrix44 clTgtXfm = IInterpMatrices(currL2W, unclTgtXfm, parm);
return clTgtXfm;
}
return unclTgtXfm;
}
void plLineFollowMod::ISetTargetTransform(int iTarg, const hsMatrix44& unclTgtXfm)
{
plCoordinateInterface* ci = IGetTargetCoordinateInterface(iTarg);
if( ci )
{
hsMatrix44 tgtXfm = fFollowFlags & kSpeedClamp ? ISpeedClamp(ci, unclTgtXfm) : unclTgtXfm;
if( fFollowFlags & kFullMatrix )
{
// This branch currently never gets taken. If it ever does,
// we should probably optimize out this GetInverse() (depending
// on how often it gets taken).
const hsMatrix44& l2w = tgtXfm;
hsMatrix44 w2l;
l2w.GetInverse(&w2l);
ci->SetTransform(l2w, w2l);
}
else
{
hsMatrix44 l2w = ci->GetLocalToWorld();
hsMatrix44 w2l = ci->GetWorldToLocal();
hsPoint3 pos = tgtXfm.GetTranslate();
hsPoint3 oldPos = l2w.GetTranslate();
l2w.SetTranslate(&pos);
hsMatrix44 xlate;
xlate.Reset();
xlate.SetTranslate(&oldPos);
w2l = w2l * xlate;
xlate.SetTranslate(&-pos);
w2l = w2l * xlate;
ci->SetTransform(l2w, w2l);
}
hsPoint3 newPos = tgtXfm.GetTranslate();
int i;
for( i = 0; i < fStereizers.GetCount(); i++ )
{
if( fStereizers[i] )
{
fStereizers[i]->SetWorldInitPos(newPos);
fStereizers[i]->Stereize();
}
}
}
}
void plLineFollowMod::ISetupStereizers(const plListenerMsg* listMsg)
{
int i;
for( i = 0; i < fStereizers.GetCount(); i++ )
{
if( fStereizers[i] )
fStereizers[i]->SetFromListenerMsg(listMsg);
}
}
void plLineFollowMod::AddTarget(plSceneObject* so)
{
plMultiModifier::AddTarget(so);
if( so )
plgDispatch::Dispatch()->RegisterForExactType(plEvalMsg::Index(), GetKey());
}
void plLineFollowMod::RemoveTarget(plSceneObject* so)
{
plMultiModifier::RemoveTarget(so);
}
void plLineFollowMod::AddStereizer(const plKey& key)
{
hsgResMgr::ResMgr()->SendRef(plKey(key), TRACKED_NEW plGenRefMsg(GetKey(), plRefMsg::kOnCreate, 0, kRefStereizer), plRefFlags::kPassiveRef);
}
void plLineFollowMod::RemoveStereizer(const plKey& key)
{
hsgResMgr::ResMgr()->SendRef(plKey(key), TRACKED_NEW plGenRefMsg(GetKey(), plRefMsg::kOnRemove, 0, kRefStereizer), plRefFlags::kPassiveRef);
}
// derived version of this class for rail cameras
// the difference is the rail camera just calculates
// the desired position but does not move the target to
// it.
plRailCameraMod::plRailCameraMod() :
fCurrentTime(0.0f),
fTargetTime(0.0f),
fFarthest(false)
{
plLineFollowMod::plLineFollowMod();
fGoal.Set(0,0,0);
}
plRailCameraMod::~plRailCameraMod()
{
}
hsBool plRailCameraMod::IGetTargetTransform(hsPoint3& searchPos, hsMatrix44& tgtXfm)
{
if (fPath->GetFarthest())
{
fFarthest = true;
fPath->SetFarthest(false);
}
fTargetTime = fPath->GetExtremePoint(searchPos);
fPath->SetCurTime(fTargetTime, plAnimPath::kCalcPosOnly);
hsPoint3 pos;
fPath->GetPosition(&pos);
tgtXfm.MakeTranslateMat((hsVector3*)&pos);
return true;
}
hsPoint3 plRailCameraMod::GetGoal(double secs, hsScalar speed)
{
hsScalar delTime;
int dir;
if (fTargetTime == fCurrentTime)
return fGoal;
if (fTargetTime > fCurrentTime)
{
dir = 1;
delTime = fTargetTime - fCurrentTime;
}
else
{
dir = -1;
delTime = fCurrentTime - fTargetTime;
}
if (fPath->GetWrap() && delTime > fPath->GetLength() * 0.5f)
dir *= -1;
if (delTime <= (secs * speed))
fCurrentTime = fTargetTime;
else
fCurrentTime += (hsScalar)((secs * speed) * dir);
if (fPath->GetWrap())
{
if (fCurrentTime > fPath->GetLength())
fCurrentTime = (fCurrentTime - fPath->GetLength());
else
if (fCurrentTime < 0.0f)
fCurrentTime = fPath->GetLength() - fCurrentTime;
}
if (fFarthest)
fPath->SetCurTime((fPath->GetLength() - fCurrentTime), plAnimPath::kCalcPosOnly);
else
fPath->SetCurTime(fCurrentTime, plAnimPath::kCalcPosOnly);
fPath->GetPosition(&fGoal);
fPath->SetCurTime(fTargetTime, plAnimPath::kCalcPosOnly);
return fGoal;
}

View File

@ -0,0 +1,175 @@
/*==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 plLineFollowMod_inc
#define plLineFollowMod_inc
#include "../pnModifier/plMultiModifier.h"
#include "hsGeometry3.h"
#include "hsMatrix44.h"
class plAnimPath;
class plSceneObject;
class plStereizer;
class plListenerMsg;
class plLineFollowMod : public plMultiModifier
{
public:
enum FollowMode {
kFollowObject,
kFollowListener,
kFollowCamera,
kFollowLocalAvatar,
};
enum RefType {
kRefParent,
kRefObject,
kRefStereizer
};
enum {
kNone = 0x0,
kFullMatrix = 0x1,
kOffsetFeet = 0x2,
kOffsetAng = 0x4,
kOffset = kOffsetFeet | kOffsetAng,
kOffsetClamp = 0x8,
kForceToLine = 0x10,
kSpeedClamp = 0x20,
kSearchPosPop = 0x40 // Temp flag, gets set every time the target pops in position
};
protected:
FollowMode fFollowMode;
UInt16 fFollowFlags;
plAnimPath* fPath;
plSceneObject* fPathParent;
plSceneObject* fRefObj;
mutable hsPoint3 fSearchPos;
hsTArray<plStereizer*> fStereizers;
hsScalar fTanOffset;
hsScalar fOffset;
hsScalar fOffsetClamp;
hsScalar fSpeedClamp;
virtual hsBool IEval(double secs, hsScalar del, UInt32 dirty);
virtual hsBool IGetSearchPos();
virtual void ISetTargetTransform(int iTarg, const hsMatrix44& tgtXfm);
virtual void ISetPathTransform();
virtual hsBool IGetTargetTransform(hsPoint3& searchPos, hsMatrix44& tgtXfm);
virtual hsBool IOffsetTargetTransform(hsMatrix44& tgtXfm);
virtual hsMatrix44 ISpeedClamp(plCoordinateInterface* ci, const hsMatrix44& unclTgtXfm);
hsMatrix44 IInterpMatrices(const hsMatrix44& m0, const hsMatrix44& m1, hsScalar parm);
void ICheckForPop(const hsPoint3& oldPos, const hsPoint3& newPos);
void ISetupStereizers(const plListenerMsg* listMsg);
void IUnRegister();
void IRegister();
public:
plLineFollowMod();
~plLineFollowMod();
CLASSNAME_REGISTER( plLineFollowMod );
GETINTERFACE_ANY( plLineFollowMod, plMultiModifier );
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
// Export time stuff
void SetPath(plAnimPath* path);
const plAnimPath* GetPath() const { return fPath; }
void SetFollowMode(FollowMode f);
FollowMode GetFollowMode() const { return fFollowMode; }
hsBool HasOffsetFeet() const { return 0 != (fFollowFlags & kOffsetFeet); }
hsBool HasOffsetDegrees() const { return 0 != (fFollowFlags & kOffsetAng); }
hsBool HasOffset() const { return 0 != (fFollowFlags & kOffset); }
hsBool HasOffsetClamp() const { return 0 != (fFollowFlags & kOffsetClamp); }
hsBool HasSpeedClamp() const { return 0 != (fFollowFlags & kSpeedClamp); }
void SetOffsetFeet(hsScalar f);
hsScalar GetOffsetFeet() const { return fOffset; }
void SetOffsetDegrees(hsScalar f);
hsScalar GetOffsetDegrees() const { return hsScalarRadToDeg(fOffset); }
void SetOffsetClamp(hsScalar f);
hsScalar GetOffsetClamp() const { return fOffsetClamp; }
void SetForceToLine(hsBool on);
hsBool GetForceToLine() const { return 0 != (fFollowFlags & kForceToLine); }
void SetSpeedClamp(hsScalar feetPerSec);
hsScalar GetSpeedClamp() const { return fSpeedClamp; }
hsBool MsgReceive(plMessage* msg);
virtual void AddTarget(plSceneObject* so);
virtual void RemoveTarget(plSceneObject* so);
void AddStereizer(const plKey& sterKey);
void RemoveStereizer(const plKey& sterKey);
};
class plRailCameraMod : public plLineFollowMod
{
public:
plRailCameraMod();
~plRailCameraMod();
CLASSNAME_REGISTER( plRailCameraMod );
GETINTERFACE_ANY( plRailCameraMod, plLineFollowMod );
void Init() { fCurrentTime = -1; } // twiddle ourselves so we get ready to go...
hsPoint3 GetGoal(double secs, hsScalar speed);
protected:
virtual void ISetTargetTransform(int iTarg, const hsMatrix44& tgtXfm) {fDesiredMatrix = tgtXfm;}
virtual hsBool IGetTargetTransform(hsPoint3& searchPos, hsMatrix44& tgtXfm);
hsMatrix44 fDesiredMatrix;
hsScalar fCurrentTime;
hsScalar fTargetTime;
hsPoint3 fGoal;
hsBool fFarthest;
};
#endif // plLineFollowMod_inc

View File

@ -0,0 +1,290 @@
/*==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 <stdlib.h>
#include "hsTypes.h"
#include "plRandomCommandMod.h"
#include "../pnSceneObject/plSceneObject.h"
#include "../plMessage/plAnimCmdMsg.h"
#include "../pnMessage/plEventCallbackMsg.h"
#include "plgDispatch.h"
#include "hsTimer.h"
#include "hsUtils.h"
static const hsScalar kRandNormalize = 1.f / 32767.f;
plRandomCommandMod::plRandomCommandMod()
{
fState = 0;
fMode = kNormal;
fCurrent = -1;
fMinDelay = 0;
fMaxDelay = 0;
}
plRandomCommandMod::~plRandomCommandMod()
{
}
// return how many are left to choose from
int plRandomCommandMod::IExcludeSelections(int ncmds)
{
if( fMode & kCoverall )
{
int nLeft = ncmds;
fExcluded.SetBit(fCurrent);
// Count how many haven't been played.
int i;
for( i = ncmds-1; i >= 0; --i )
{
if( fExcluded.IsBitSet(i) )
nLeft--;
}
// If we're out of cmds, and OneCycle is set,
// we're out of cmds until the next play.
// Go ahead and reset for that.
// If we're out and OneCycle isn't set, then go ahead
// and set up for a new cycle.
if( !nLeft )
{
fExcluded.Clear();
if( fMode & kNoRepeats )
fExcluded.SetBit(fCurrent);
if( fMode & kOneCycle )
return 0;
nLeft = ncmds;
if( ( fMode & kNoRepeats ) && ncmds > 1 )
nLeft--;
}
return nLeft;
}
double currTime = hsTimer::GetSysSeconds();
fExcluded.Clear();
int i;
for( i = 0; i < fEndTimes.GetCount(); i++ )
{
if( fEndTimes[i] > currTime )
{
ncmds--;
fExcluded.SetBit(i);
}
}
if( fMode & kNoRepeats )
{
ncmds--;
fExcluded.SetBit(fCurrent);
return ncmds;
}
return ncmds;
}
hsScalar plRandomCommandMod::IGetDelay(hsScalar len) const
{
hsScalar r = float(hsRand() * kRandNormalize);
hsScalar delay = fMinDelay + (fMaxDelay - fMinDelay) * r;
if( fMode & kDelayFromEnd )
delay += len;
if( delay < 0 )
delay = fmodf(len, -delay);
return delay;
}
hsBool plRandomCommandMod::ISelectNext(int ncmds)
{
if( fMode & kSequential )
{
if( ++fCurrent >= ncmds )
{
if( fMode & kOneCycle )
{
fCurrent = -1;
return false;
}
fCurrent = 0;
}
return true;
}
hsScalar r = float(hsRand() * kRandNormalize);
int nSelect = ncmds;
if( fCurrent >= 0 )
nSelect = IExcludeSelections(ncmds);
if( !nSelect )
return false;
int nth = int(r * (float(nSelect)-1.e-3f));
int iNext = 0;
int i;
for( i = 0; i < ncmds; i++ )
{
if( !fExcluded.IsBitSet(i) )
{
if( !nth-- )
{
iNext = i;
break;
}
}
}
fCurrent = iNext;
return true;
}
void plRandomCommandMod::IStart()
{
if( !IStopped() )
return;
fState &= ~kStopped;
IPlayNextIfMaster();
}
void plRandomCommandMod::IStop()
{
fState |= kStopped;
}
hsBool plRandomCommandMod::IStopped() const
{
return 0 != (fState & kStopped);
}
void plRandomCommandMod::IPlayNextIfMaster()
{
if( !fTarget )
IRetry(2.f);
if( fTarget->IsLocallyOwned() == plSynchedObject::kNo ) // if this object is a proxy, it should just wait for network cmds
return;
if( IStopped() )
return;
IPlayNext();
}
hsBool plRandomCommandMod::MsgReceive(plMessage* msg)
{
// plAnimCmdMsg - interpret start/stop appropriately.
// could overinterpret set loop points to limit range of
// cmds we use to a window of the total set.
plAnimCmdMsg* anim = plAnimCmdMsg::ConvertNoRef(msg);
if( anim )
{
if( anim->GetSender() != GetKey() )
{
#if 0
hsStatusMessageF("someone triggered me, remote=%d\n",
msg->HasBCastFlag(plMessage::kNetNonLocal));
#endif
if( anim->Cmd(plAnimCmdMsg::kContinue) )
IStart();
if( anim->Cmd(plAnimCmdMsg::kStop) )
IStop();
if( anim->Cmd(plAnimCmdMsg::kToggleState) )
{
if( IStopped() )
IStart();
else
IStop();
}
}
else
{
#if 0
hsStatusMessageF("play next if master, remote=%d\n",
msg->HasBCastFlag(plMessage::kNetNonLocal));
#endif
IPlayNextIfMaster();
}
return true;
}
// Don't understand, pass on to base class.
return plSingleModifier::MsgReceive(msg);
}
void plRandomCommandMod::IReset()
{
fCurrent = -1;
fExcluded.Clear();
if( !IStopped() )
IRetry(0);
}
void plRandomCommandMod::Read(hsStream* s, hsResMgr* mgr)
{
plSingleModifier::Read(s, mgr);
fMode = s->ReadByte();
fState = s->ReadByte();
fMinDelay = s->ReadSwapScalar();
fMaxDelay = s->ReadSwapScalar();
IReset();
}
void plRandomCommandMod::Write(hsStream* s, hsResMgr* mgr)
{
plSingleModifier::Write(s, mgr);
s->WriteByte(fMode);
s->WriteByte(fState);
s->WriteSwapScalar(fMinDelay);
s->WriteSwapScalar(fMaxDelay);
}
void plRandomCommandMod::IRetry(hsScalar secs)
{
IStop();
double t = hsTimer::GetSysSeconds() + secs;
plAnimCmdMsg* msg = TRACKED_NEW plAnimCmdMsg(nil, GetKey(), &t);
msg->SetCmd(plAnimCmdMsg::kContinue);
plgDispatch::MsgSend(msg);
}

View File

@ -0,0 +1,111 @@
/*==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 plRandomCommandMod_inc
#define plRandomCommandMod_inc
#include "../pnModifier/plSingleModifier.h"
#include "hsTemplates.h"
class plRandomCommandMod : public plSingleModifier
{
public:
enum {
kNormal = 0x0, // randomly select the next
kNoRepeats = 0x1, // random, but no cmd twice in a row
kCoverall = 0x2, // random, but no cmd played twice till all cmds played
kOneCycle = 0x4, // after playing through all cmds, stop
kOneCmd = 0x8, // after playing a random cmd, stop until started again.
kDelayFromEnd = 0x10,
kSequential = 0x20
};
enum {
kStopped = 0x1
};
protected:
// These are only lightly synched, the only synched state is whether
// they are currently active.
UInt8 fState;
hsBitVector fExcluded;
Int8 fCurrent;
UInt8 fMode; // static, if it becomes dynamic, move to SynchedValue
hsTArray<double> fEndTimes;
hsScalar fMinDelay;
hsScalar fMaxDelay;
void IStart();
virtual void IStop();
hsBool IStopped() const;
void IRetry(hsScalar secs);
virtual void IPlayNextIfMaster();
void IReset();
hsScalar IGetDelay(hsScalar len) const;
int IExcludeSelections(int ncmds);
hsBool ISelectNext(int nAnim); // return false if we should stop, else set fCurrent to next index
// Once fCurrent is set to the next animation index to play,
// IPlayNext() does whatever it takes to actually play it.
virtual void IPlayNext() = 0;
// We only act in response to messages.
virtual hsBool IEval(double secs, hsScalar del, UInt32 dirty) { return false; }
public:
plRandomCommandMod();
~plRandomCommandMod();
CLASSNAME_REGISTER( plRandomCommandMod );
GETINTERFACE_ANY( plRandomCommandMod, plSingleModifier );
virtual hsBool MsgReceive(plMessage* pMsg);
virtual void Read(hsStream* s, hsResMgr* mgr);
virtual void Write(hsStream* s, hsResMgr* mgr);
// Export only
void SetMode(UInt8 m) { fMode = m; }
UInt8 GetMode() const { return fMode; }
void SetState(UInt8 s) { fState = s; }
UInt8 GetState() const { return fState; }
void SetMinDelay(hsScalar f) { fMinDelay = f; }
hsScalar GetMinDelay() const { return fMinDelay; }
void SetMaxDelay(hsScalar f) { fMaxDelay = f; }
hsScalar GetMaxDelay() const { return fMaxDelay; }
};
#endif // plRandomCommandMod_inc

View File

@ -0,0 +1,294 @@
/*==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 <math.h>
#include "hsTypes.h"
#include "plStereizer.h"
#include "plLineFollowMod.h"
#include "../plMessage/plListenerMsg.h"
#include "plgDispatch.h"
#include "../pnSceneObject/plSceneObject.h"
#include "../pnSceneObject/plCoordinateInterface.h"
#include "hsFastMath.h"
#include "hsGeometry3.h"
#include "hsMatrix44.h"
#include "hsStream.h"
plStereizer::plStereizer()
: fInitPos(0,0,0),
fListPos(0,0,0),
fListDirection(0,1.f,0),
fListUp(0,0,1.f)
{
}
plStereizer::~plStereizer()
{
if( !HasMaster() )
plgDispatch::Dispatch()->UnRegisterForExactType(plListenerMsg::Index(), GetKey());
}
void plStereizer::Read(hsStream* stream, hsResMgr* mgr)
{
plSingleModifier::Read(stream, mgr);
fAmbientDist = stream->ReadSwapScalar();
fTransition = stream->ReadSwapScalar();
fMaxSepDist = stream->ReadSwapScalar();
fMinSepDist = stream->ReadSwapScalar();
fTanAng = stream->ReadSwapScalar();
fInitPos.Read(stream);
if( !HasMaster() )
plgDispatch::Dispatch()->RegisterForExactType(plListenerMsg::Index(), GetKey());
}
void plStereizer::Write(hsStream* stream, hsResMgr* mgr)
{
plSingleModifier::Write(stream, mgr);
stream->WriteSwapScalar(fAmbientDist);
stream->WriteSwapScalar(fTransition);
stream->WriteSwapScalar(fMaxSepDist);
stream->WriteSwapScalar(fMinSepDist);
stream->WriteSwapScalar(fTanAng);
fInitPos.Write(stream);
}
hsBool plStereizer::MsgReceive(plMessage* msg)
{
plListenerMsg* listenMsg = plListenerMsg::ConvertNoRef(msg);
if( listenMsg )
{
SetFromListenerMsg(listenMsg);
return Stereize();
}
return plSingleModifier::MsgReceive(msg);
}
hsBool plStereizer::IEval(double secs, hsScalar del, UInt32 dirty)
{
return false;
}
hsBool plStereizer::Stereize()
{
plSceneObject* targ = GetTarget();
if( !targ )
return true;
targ->FlushTransform();
// Find distance to listener
hsPoint3 pos = IGetUnStereoPos();
hsVector3 posToList(&fListPos, &pos);
hsScalar dist = posToList.Magnitude();
// If distance less than ambient distance
// setup as pure ambient
// Else if distance greater than ambient distance + transition
// setup as pure localized
// Else
// Calc pure ambient position
// Calc pure localized position
// Interpolate between the two.
if( dist <= fAmbientDist )
{
ISetNewPos(IGetAmbientPos());
}
else if( dist >= fAmbientDist + fTransition )
{
ISetNewPos(IGetLocalizedPos(posToList, dist));
}
else
{
hsPoint3 ambPos = IGetAmbientPos();
hsPoint3 localizePos = IGetLocalizedPos(posToList, dist);
hsPoint3 newPos(ambPos);
newPos += (localizePos - ambPos) * ((dist - fAmbientDist) / fTransition);
ISetNewPos(newPos);
}
return true;
}
void plStereizer::ISetNewPos(const hsPoint3& newPos)
{
hsMatrix44 l2w = GetTarget()->GetLocalToWorld();
hsMatrix44 w2l = GetTarget()->GetWorldToLocal();
l2w.NotIdentity();
l2w.fMap[0][3] = newPos[0];
l2w.fMap[1][3] = newPos[1];
l2w.fMap[2][3] = newPos[2];
hsPoint3 invPos = -newPos;
w2l.fMap[0][3] = ((hsVector3*)&w2l.fMap[0][0])->InnerProduct(invPos);
w2l.fMap[1][3] = ((hsVector3*)&w2l.fMap[1][0])->InnerProduct(invPos);
w2l.fMap[2][3] = ((hsVector3*)&w2l.fMap[2][0])->InnerProduct(invPos);
IGetTargetCoordinateInterface(0)->SetTransform(l2w, w2l);
}
void plStereizer::SetFromListenerMsg(const plListenerMsg* listMsg)
{
fListPos = listMsg->GetPosition();
fListDirection = listMsg->GetDirection();
fListUp = listMsg->GetUp();
}
hsPoint3 plStereizer::IGetAmbientPos() const
{
hsPoint3 pos = fListPos;
hsVector3 axOut = fListDirection % fListUp;
hsFastMath::NormalizeAppr(axOut);
if( IsLeftChannel() )
axOut *= -fMinSepDist;
else
axOut *= fMinSepDist;
pos += axOut;
return pos;
}
hsPoint3 plStereizer::IGetLocalizedPos(const hsVector3& posToList, hsScalar distToList) const
{
hsPoint3 pos = IGetUnStereoPos();
hsVector3 axOut(-posToList.fY, posToList.fX, 0);
hsFastMath::NormalizeAppr(axOut);
hsScalar distOut = distToList * fTanAng;
if( distOut > fMaxSepDist )
distOut = fMaxSepDist;
else if( distOut < fMinSepDist )
distOut = fMinSepDist;
if( IsLeftChannel() )
distOut = -distOut;
axOut *= distOut;
pos += axOut;
return pos;
}
void plStereizer::SetSepAngle(hsScalar rads)
{
fTanAng = hsScalar(tan(rads));
}
hsScalar plStereizer::GetSepAngle() const
{
return atan(fTanAng);
}
hsPoint3 plStereizer::IGetUnStereoPos() const
{
return GetWorldInitPos();
}
void plStereizer::SetWorldInitPos(const hsPoint3& pos)
{
plCoordinateInterface* parent = IGetParent();
if( parent )
fInitPos = parent->GetWorldToLocal() * pos;
else
fInitPos = pos;
}
hsPoint3 plStereizer::GetWorldInitPos() const
{
plCoordinateInterface* parent = IGetParent();
if( parent )
return parent->GetLocalToWorld() * fInitPos;
return fInitPos;
}
plCoordinateInterface* plStereizer::IGetParent() const
{
plCoordinateInterface* coord = IGetTargetCoordinateInterface(0);
if( coord )
{
return coord->GetParent();
}
return nil;
}
// Note that (along with it's many other hacky defects), this
// will go down in flames if there are two potential masters.
// Of course, two line follow mods doesn't really make sense
// now anyway, but the point is that this is a simplified placeholder
// to get the job done. If and when a need is shown for sequencing of
// modifiers, this should be updated to follow that protocol. But
// the rationale is that one simple example of a need for sequencing
// doesn't give enough basis to decide what that protocol should be.
// Or in simpler terms, I want to do it one way, Brice wants to do
// it another, and since either would work for this, we're waiting
// for a tie breaker case that gives one way or the other an advantage.
hsBool plStereizer::CheckForMaster()
{
ISetHasMaster(false);
plSceneObject* targ = GetTarget();
if( !targ )
return false;
int n = targ->GetNumModifiers();
int i;
for( i = 0; i < n; i++ )
{
plLineFollowMod* line = plLineFollowMod::ConvertNoRef(IGetTargetModifier(0, i));
if( line )
{
ISetHasMaster(true);
line->AddStereizer(GetKey());
return true;
}
}
return false;
}

View File

@ -0,0 +1,124 @@
/*==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 plStereizer_inc
#define plStereizer_inc
#include "../pnModifier/plSingleModifier.h"
#include "hsGeometry3.h"
#include "hsMatrix44.h"
class plListenerMsg;
class plMessage;
class plCoordinateInterface;
class hsStream;
class hsResMgr;
class plStereizer : public plSingleModifier
{
protected:
// Flags - in a plSingleModifier::hsBitVector.
enum
{
kLeftChannel,
kHasMaster
};
// Static properties
hsScalar fAmbientDist;
hsScalar fTransition;
hsScalar fMaxSepDist;
hsScalar fMinSepDist;
hsScalar fTanAng;
hsPoint3 fInitPos;
// Environmental properties, namely of the current listener
hsPoint3 fListPos;
hsVector3 fListDirection;
hsVector3 fListUp;
virtual hsBool IEval(double secs, hsScalar del, UInt32 dirty);
hsPoint3 IGetLocalizedPos(const hsVector3& posToList, hsScalar distToList) const;
hsPoint3 IGetAmbientPos() const;
void ISetNewPos(const hsPoint3& newPos);
hsPoint3 IGetUnStereoPos() const;
plCoordinateInterface* IGetParent() const;
void ISetHasMaster(hsBool on) { if(on)SetFlag(kHasMaster); else ClearFlag(kHasMaster); }
public:
plStereizer();
virtual ~plStereizer();
CLASSNAME_REGISTER( plStereizer );
GETINTERFACE_ANY( plStereizer, plSingleModifier );
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
virtual hsBool MsgReceive(plMessage* msg);
hsBool Stereize();
void SetFromListenerMsg(const plListenerMsg* listMsg);
void SetAmbientDist(hsScalar d) { fAmbientDist = d; }
hsScalar GetAmbientDist() const { return fAmbientDist; }
void SetTransition(hsScalar d) { fTransition = d; }
hsScalar GetTransition() const { return fTransition; }
void SetMaxSepDist(hsScalar d) { fMaxSepDist = d; }
hsScalar GetMaxSepDist() const { return fMaxSepDist; }
void SetMinSepDist(hsScalar d) { fMinSepDist = d; }
hsScalar GetMinSepDist() const { return fMinSepDist; }
void SetSepAngle(hsScalar rads);
hsScalar GetSepAngle() const;
void SetAsLeftChannel(hsBool on) { if(on)SetFlag(kLeftChannel); else ClearFlag(kLeftChannel); }
hsBool IsLeftChannel() const { return HasFlag(kLeftChannel); }
void SetParentInitPos(const hsPoint3& pos) { fInitPos = pos; }
const hsPoint3& GetParentInitPos() const { return fInitPos; }
void SetWorldInitPos(const hsPoint3& pos);
hsPoint3 GetWorldInitPos() const;
hsBool CheckForMaster();
hsBool HasMaster() const { return HasFlag(kHasMaster); }
};
#endif // plStereizer_inc

View File

@ -0,0 +1,432 @@
/*==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 "plViewFaceModifier.h"
#include "plgDispatch.h"
#include "../pnSceneObject/plSceneObject.h"
#include "../pnSceneObject/plCoordinateInterface.h"
#include "hsFastMath.h"
#include "plPipeline.h"
#include "../plMessage/plRenderMsg.h"
#include "../plMessage/plListenerMsg.h"
#include "../plMessage/plAvatarMsg.h"
#include "../plAvatar/plAvBrainHuman.h"
#include "../plAvatar/plArmatureMod.h"
plViewFaceModifier::plViewFaceModifier()
: fFacePoint(0,0,0),
fLastDirY(0,1.f,0),
fScale(1.f,1.f,1.f),
fOffset(0,0,0)
{
fOrigLocalToParent.Reset();
fOrigParentToLocal.Reset();
SetFlag(kFaceCam); // default
}
plViewFaceModifier::~plViewFaceModifier()
{
}
void plViewFaceModifier::SetOrigTransform(const hsMatrix44& l2p, const hsMatrix44& p2l)
{
fOrigLocalToParent = l2p;
fOrigParentToLocal = p2l;
}
void plViewFaceModifier::Read(hsStream* s, hsResMgr* mgr)
{
plSingleModifier::Read(s, mgr);
fScale.Read(s);
fOrigLocalToParent.Read(s);
fOrigParentToLocal.Read(s);
if( HasFlag(kFaceObj) )
mgr->ReadKeyNotifyMe(s, TRACKED_NEW plGenRefMsg(GetKey(), plRefMsg::kOnCreate, 0, kRefFaceObj), plRefFlags::kPassiveRef);
fOffset.Read(s);
if( HasFlag(kMaxBounds) )
fMaxBounds.Read(s);
}
void plViewFaceModifier::Write(hsStream* s, hsResMgr* mgr)
{
plSingleModifier::Write(s, mgr);
fScale.Write(s);
fOrigLocalToParent.Write(s);
fOrigParentToLocal.Write(s);
if( HasFlag(kFaceObj) )
mgr->WriteKey(s, fFaceObj);
fOffset.Write(s);
if( HasFlag(kMaxBounds) )
fMaxBounds.Write(s);
}
void plViewFaceModifier::SetMaxBounds(const hsBounds3Ext& bnd)
{
SetFlag(kMaxBounds);
fMaxBounds = bnd;
}
void plViewFaceModifier::SetTarget(plSceneObject* so)
{
plSingleModifier::SetTarget(so);
plgDispatch::Dispatch()->RegisterForExactType(plRenderMsg::Index(), GetKey());
if( HasFlag(kFaceList) )
plgDispatch::Dispatch()->RegisterForExactType(plListenerMsg::Index(), GetKey());
if( HasFlag(kFacePlay) )
plgDispatch::Dispatch()->RegisterForExactType(plArmatureUpdateMsg::Index(), GetKey());
}
hsBool plViewFaceModifier::IEval(double secs, hsScalar del, UInt32 dirty)
{
return false;
}
hsBool plViewFaceModifier::IFacePoint(plPipeline* pipe, const hsPoint3& at)
{
#if 1 // BOUNDSTEST
extern int mfCurrentTest;
if( mfCurrentTest != 101 )
if( HasFlag(kMaxBounds) )
{
if( !pipe->TestVisibleWorld(fMaxBounds) )
return false;
}
#endif // BOUNDSTEST
if( !(GetTarget() && GetTarget()->GetCoordinateInterface()) )
return false;
hsMatrix44 worldToLocal = fOrigParentToLocal; // parentToLocal
if( GetTarget()->GetCoordinateInterface()->GetParent() && GetTarget()->GetCoordinateInterface()->GetParent() )
{
hsMatrix44 m;
worldToLocal = worldToLocal * GetTarget()->GetCoordinateInterface()->GetParent()->GetWorldToLocal();
}
hsPoint3 localAt = worldToLocal * at;
hsScalar len = localAt.MagnitudeSquared();
if( len <= 0 )
return false;
len = -hsFastMath::InvSqrtAppr(len);
hsVector3 dirX, dirY, dirZ;
dirZ.Set(localAt.fX * len, localAt.fY * len, localAt.fZ * len);
if( HasFlag(kPivotFace) )
{
dirY.Set(0.f, 0.f, 1.f);
dirX = dirY % dirZ;
dirX = hsFastMath::NormalizeAppr(dirX);
dirY = dirZ % dirX;
}
else if( HasFlag(kPivotFavorY) )
{
dirY.Set(0.f, 1.f, 0.f);
dirX = dirY % dirZ;
dirX = hsFastMath::NormalizeAppr(dirX);
dirY = dirZ % dirX;
}
else if( HasFlag(kPivotY) )
{
dirY.Set(0.f, 1.f, 0.f);
dirX = dirY % dirZ;
dirX = hsFastMath::NormalizeAppr(dirX);
dirZ = dirX % dirY;
}
else if( HasFlag(kPivotTumble) )
{
dirY = fLastDirY;
dirX = dirY % dirZ;
dirX = hsFastMath::NormalizeAppr(dirX);
dirY = dirZ % dirX;
fLastDirY = dirY;
}
else
{
hsAssert(false, "I've no idea what you're getting at here in ViewFace land");
}
hsMatrix44 x;
hsMatrix44 xInv;
xInv.fMap[0][0] = x.fMap[0][0] = dirX[0];
xInv.fMap[1][0] = x.fMap[0][1] = dirY[0];
xInv.fMap[2][0] = x.fMap[0][2] = dirZ[0];
xInv.fMap[3][0] = x.fMap[0][3] = 0;
xInv.fMap[0][1] = x.fMap[1][0] = dirX[1];
xInv.fMap[1][1] = x.fMap[1][1] = dirY[1];
xInv.fMap[2][1] = x.fMap[1][2] = dirZ[1];
xInv.fMap[3][1] = x.fMap[1][3] = 0;
xInv.fMap[0][2] = x.fMap[2][0] = dirX[2];
xInv.fMap[1][2] = x.fMap[2][1] = dirY[2];
xInv.fMap[2][2] = x.fMap[2][2] = dirZ[2];
xInv.fMap[3][2] = x.fMap[2][3] = 0;
x.fMap[3][0] = x.fMap[3][1] = x.fMap[3][2] = 0;
xInv.fMap[0][3] = xInv.fMap[1][3] = xInv.fMap[2][3] = 0;
xInv.fMap[3][3] = x.fMap[3][3] = hsScalar1;
x.NotIdentity();
xInv.NotIdentity();
if( HasFlag(kScale) )
{
x.fMap[0][0] *= fScale.fX;
x.fMap[0][1] *= fScale.fX;
x.fMap[0][2] *= fScale.fX;
x.fMap[1][0] *= fScale.fY;
x.fMap[1][1] *= fScale.fY;
x.fMap[1][2] *= fScale.fY;
x.fMap[2][0] *= fScale.fZ;
x.fMap[2][1] *= fScale.fZ;
x.fMap[2][2] *= fScale.fZ;
hsScalar inv = 1.f / fScale.fX;
xInv.fMap[0][0] *= inv;
xInv.fMap[1][0] *= inv;
xInv.fMap[2][0] *= inv;
inv = 1.f / fScale.fY;
xInv.fMap[0][1] *= inv;
xInv.fMap[1][1] *= inv;
xInv.fMap[2][1] *= inv;
inv = 1.f / fScale.fZ;
xInv.fMap[0][2] *= inv;
xInv.fMap[1][2] *= inv;
xInv.fMap[2][2] *= inv;
}
hsMatrix44 l2p = fOrigLocalToParent * x;
hsMatrix44 p2l = xInv * fOrigParentToLocal;
if( l2p != IGetTargetCoordinateInterface(0)->GetLocalToParent() ) // TERRORDAN
{
IGetTargetCoordinateInterface(0)->SetLocalToParent(l2p, p2l);
IGetTargetCoordinateInterface(0)->FlushTransform(false);
}
return true;
}
#include "plProfile.h"
plProfile_CreateTimer("ViewFacing", "RenderSetup", ViewFace);
hsBool plViewFaceModifier::MsgReceive(plMessage* msg)
{
plRenderMsg* rend = plRenderMsg::ConvertNoRef(msg);
if( rend )
{
plProfile_BeginLap(ViewFace, this->GetKey()->GetUoid().GetObjectName());
if( HasFlag(kFaceCam) )
{
fFacePoint = rend->Pipeline()->GetViewPositionWorld();
if( HasFlag(kOffset) )
{
if( HasFlag(kOffsetLocal) )
{
fFacePoint += rend->Pipeline()->GetViewAcrossWorld() * fOffset.fX;
fFacePoint += rend->Pipeline()->GetViewUpWorld() * fOffset.fY;
fFacePoint += rend->Pipeline()->GetViewDirWorld() * fOffset.fZ;
}
else
{
fFacePoint += fOffset;
}
}
}
else
if( HasFlag(kFaceObj) )
{
if( !fFaceObj )
return true;
fFacePoint = fFaceObj->GetLocalToWorld().GetTranslate();
if( HasFlag(kOffset) )
{
if( HasFlag(kOffsetLocal) )
fFacePoint += fFaceObj->GetLocalToWorld() * fOffset;
else
fFacePoint += fOffset;
}
}
IFacePoint(rend->Pipeline(), fFacePoint);
plProfile_EndLap(ViewFace, this->GetKey()->GetUoid().GetObjectName());
return true;
}
plArmatureUpdateMsg* armMsg = plArmatureUpdateMsg::ConvertNoRef(msg);
if( armMsg && armMsg->IsLocal() )
{
const plSceneObject* head = armMsg->fArmature->FindBone(plAvBrainHuman::Head);
if( head )
{
fFacePoint = head->GetLocalToWorld().GetTranslate();
if( HasFlag(kOffset) )
{
if( HasFlag(kOffsetLocal) )
fFacePoint += head->GetLocalToWorld() * fOffset;
else
fFacePoint += fOffset;
}
}
return true;
}
plListenerMsg* list = plListenerMsg::ConvertNoRef(msg);
if( list )
{
fFacePoint = list->GetPosition();
if( HasFlag(kOffset) )
{
if( HasFlag(kOffsetLocal) )
{
fFacePoint += (list->GetDirection() % list->GetUp()) * fOffset.fX;
fFacePoint += list->GetDirection() * fOffset.fY;
fFacePoint += list->GetUp() * fOffset.fZ;
}
else
{
fFacePoint += fOffset;
}
}
return true;
}
plGenRefMsg* refMsg = plGenRefMsg::ConvertNoRef(msg);
if( refMsg )
{
if( refMsg->GetContext() & (plRefMsg::kOnCreate|plRefMsg::kOnRequest|plRefMsg::kOnReplace) )
IOnReceive(refMsg);
else
IOnRemove(refMsg);
return true;
}
return plSingleModifier::MsgReceive(msg);
}
void plViewFaceModifier::IOnReceive(plGenRefMsg* refMsg)
{
switch(refMsg->fType)
{
case kRefFaceObj:
fFaceObj = plSceneObject::ConvertNoRef(refMsg->GetRef());
break;
}
}
void plViewFaceModifier::IOnRemove(plGenRefMsg* refMsg)
{
switch(refMsg->fType)
{
case kRefFaceObj:
fFaceObj = nil;
break;
}
}
void plViewFaceModifier::ISetObject(plKey soKey)
{
hsgResMgr::ResMgr()->SendRef(soKey, TRACKED_NEW plGenRefMsg(GetKey(), plRefMsg::kOnRequest, 0, kRefFaceObj), plRefFlags::kPassiveRef);
}
void plViewFaceModifier::SetFollowMode(FollowMode m, plKey soKey)
{
ClearFlag(kFaceCam);
ClearFlag(kFaceList);
ClearFlag(kFacePlay);
ClearFlag(kFaceObj);
switch(m)
{
case kFollowCamera:
SetFlag(kFaceCam);
break;
case kFollowListener:
SetFlag(kFaceList);
break;
case kFollowPlayer:
SetFlag(kFacePlay);
break;
case kFollowObject:
SetFlag(kFaceObj);
ISetObject(soKey);
break;
default:
hsAssert(false, "Unknown follow mode");
SetFlag(kFaceCam);
break;
}
}
plViewFaceModifier::FollowMode plViewFaceModifier::GetFollowMode() const
{
if( HasFlag(kFaceCam) )
return kFollowCamera;
if( HasFlag(kFaceList) )
return kFollowListener;
if( HasFlag(kFacePlay) )
return kFollowPlayer;
if( HasFlag(kFaceObj) )
return kFollowObject;
hsAssert(false, "Have no follow mode");
return kFollowCamera;
}
void plViewFaceModifier::SetOffset(const hsVector3& off, hsBool local)
{
fOffset = off;
if( local )
SetFlag(kOffsetLocal);
else
ClearFlag(kOffsetLocal);
}

View File

@ -0,0 +1,124 @@
/*==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 plViewFaceModifier_inc
#define plViewFaceModifier_inc
#include "hsMatrix44.h"
#include "hsBounds.h"
#include "../pnModifier/plSingleModifier.h"
class plGenRefMsg;
class plPipeline;
class plViewFaceModifier : public plSingleModifier
{
public:
enum plVFFlags {
kPivotFace = 0,
kPivotFavorY,
kPivotY,
kPivotTumble,
kScale,
kFaceCam,
kFaceList,
kFacePlay,
kFaceObj,
kOffset,
kOffsetLocal,
kMaxBounds
};
protected:
hsVector3 fLastDirY;
hsVector3 fScale;
hsMatrix44 fOrigLocalToParent;
hsMatrix44 fOrigParentToLocal;
hsPoint3 fFacePoint;
plSceneObject* fFaceObj;
hsVector3 fOffset;
hsBounds3Ext fMaxBounds;
virtual hsBool IFacePoint(plPipeline* pipe, const hsPoint3& at);
virtual hsBool IEval(double secs, hsScalar del, UInt32 dirty);
enum RefType
{
kRefFaceObj
};
void IOnReceive(plGenRefMsg* refMsg);
void IOnRemove(plGenRefMsg* refMsg);
void ISetObject(plKey soKey);
public:
plViewFaceModifier();
virtual ~plViewFaceModifier();
CLASSNAME_REGISTER( plViewFaceModifier );
GETINTERFACE_ANY( plViewFaceModifier, plSingleModifier );
virtual void SetTarget(plSceneObject* so);
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
virtual hsBool MsgReceive(plMessage* msg);
// ViewFace specific
void SetScale(const hsVector3& s) { fScale = s; }
const hsVector3& GetScale() const { return fScale; }
void SetOrigTransform(const hsMatrix44& l2p, const hsMatrix44& p2l);
void SetMaxBounds(const hsBounds3Ext& bnd);
const hsBounds3Ext& GetMaxBounds() const { return fMaxBounds; }
hsBool HaveMaxBounds() const { return HasFlag(kMaxBounds); }
enum FollowMode
{
kFollowCamera = 0, // Follow the camera
kFollowListener,
kFollowPlayer,
kFollowObject
};
void SetFollowMode(FollowMode m, plKey soKey=nil); // For follow object, set obj, else it's ignored.
FollowMode GetFollowMode() const;
plSceneObject* GetFollowObject() const { return fFaceObj; }
void SetOffsetActive(hsBool on) { if(on) SetFlag(kOffset); else ClearFlag(kOffset); }
hsBool GetOffsetActive() const { return HasFlag(kOffset); }
void SetOffset(const hsVector3& off, hsBool local=true);
const hsVector3& GetOffset() const { return fOffset; }
hsBool GetOffsetLocal() const { return HasFlag(kOffsetLocal); }
};
#endif // plViewFaceModifier_inc

View File

@ -0,0 +1,40 @@
/*==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 pfAudioCreatable_inc
#define pfAudioCreatable_inc
#include "../pnFactory/plCreator.h"
#include "plListener.h"
REGISTER_CREATABLE( plListener );
#include "plRandomSoundMod.h"
REGISTER_CREATABLE( plRandomSoundMod );
#endif // pfCharacterCreatable_inc

View File

@ -0,0 +1,312 @@
/*==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 "hsTypes.h"
#include "plListener.h"
#include "plgDispatch.h"
#include "../plAudio/plAudioSystem.h"
#include "../pnMessage/plTimeMsg.h"
#include "../pnMessage/plAudioSysMsg.h"
#include "../pnKeyedObject/plKey.h"
#include "../pnSceneObject/plSceneObject.h"
#include "../pnSceneObject/plCoordinateInterface.h"
#include "../pnSceneObject/plSimulationInterface.h"
#include "../pfCamera/plVirtualCamNeu.h"
#include "../plMessage/plListenerMsg.h"
#include "../plNetClient/plNetClientMgr.h"
#include "../plPipeline/plDebugText.h"
#include "../plAvatar/plAvatarMgr.h"
#include "../plAvatar/plArmatureMod.h"
#include "../plAvatar/plAvCallbackAction.h"
hsBool plListener::fPrintDbgInfo = false;
hsBool plListener::IEval(double secs, hsScalar del, UInt32 dirty)
{
// if (!plgAudioSys::Active())
// return true;
plSceneObject *pRefObject = nil;
int y = 16 + 12, x = 400;
if( fPrintDbgInfo )
plDebugText::Instance().DrawString( x, 16, "Listener:", (UInt32)0xffffffff, plDebugText::kStyleBold );
// Get the avatar's SceneObject
plKey key = plNetClientMgr::GetInstance()->GetLocalPlayerKey();
if(key)
pRefObject = plSceneObject::ConvertNoRef(key->ObjectIsLoaded());
if( pRefObject == nil && fVCam == nil )
{
// We don't have a position to init by, so do NOT eval yet!!!
if( fPrintDbgInfo )
plDebugText::Instance().DrawString( x, y, "Not eval-ing yet", (UInt32)0xffffffff );
return true;
}
// Changed 2.19.02 mcn - Basing it off the head bone isn't what we really want, esp. since
// it isn't what the camera uses. What we *really* want is a head-ish-positioned non-bobbing node
// that we base both off of. Until then, we're just going to have to use the avatar's root (i.e. his
// feet) and add in an appropriate height. See plAvBrain.cpp::BindAudioListener() for the other half
// of the hack.
// Note the 2nd: since GetAxis() is buggy, we'll just add in a constant vector. Of course, this implies
// that the avatar is always oriented up, but then it also implies he's always of constant height, so
// there.
const hsVector3 kAvatarHeightVector = hsVector3( 0, 0, 6.33f ); // isn't *everyone* 6'4"?
/// Collect the current values for our parameters
hsPoint3 position;
hsVector3 velocity, dir, up;
enum
{
kInvalid = 0,
kVCam,
kObject
} facingType = kInvalid, posType = kInvalid, velType = kInvalid;
// Facing
if( fFacingRatio == 1.f )
{
if( pRefObject != nil && pRefObject->GetCoordinateInterface() )
{
hsMatrix44 facingL2W = pRefObject->GetCoordinateInterface()->GetLocalToWorld();
dir = facingL2W.GetAxis( hsMatrix44::kView );
up = facingL2W.GetAxis( hsMatrix44::kUp );
facingType = kObject;
}
}
else if( fVCam != nil )
{
dir = hsVector3( fVCam->GetCameraPOA() - fVCam->GetCameraPos() );
up = fVCam->GetCameraUp();
facingType = kVCam;
}
// Position
if( fPosRatio == 1.f )
{
if( pRefObject != nil && pRefObject->GetCoordinateInterface() )
{
position = pRefObject->GetCoordinateInterface()->GetLocalToWorld().GetTranslate();
position += kAvatarHeightVector;
posType = kObject;
}
}
else if( fVCam != nil )
{
position = fVCam->GetCameraPos();
posType = kVCam;
}
// Velocity
if( fVelRatio == 1.f )
{
if( pRefObject != nil )
{
plArmatureMod* arm = plAvatarMgr::GetInstance()->GetLocalAvatar();
if (arm)
{
plPhysicalControllerCore* controller = arm->GetController();
if (controller)
{
velocity = controller->GetLinearVelocity();
velType = kObject;
}
}
}
}
else if( fVCam != nil )
{
// Darn, can't do it
}
if( facingType == kInvalid || posType == kInvalid || velType == kInvalid )
{
if( fPrintDbgInfo )
plDebugText::Instance().DrawString( x, y, "Not eval-ing: missing one or more parameter bases", (UInt32)0xff0000ff );
return true;
}
// Got the params, now construct and send out the message, as well as update the audio system
plListenerMsg* msg = TRACKED_NEW plListenerMsg;
msg->SetDirection( dir );
msg->SetUp( up );
msg->SetPosition( position );
msg->SetVelocity( velocity );
plgAudioSys::SetListenerOrientation( dir, up );
plgAudioSys::SetListenerPos( position );
plgAudioSys::SetListenerVelocity( velocity );
if( fPrintDbgInfo )
{
char str[ 256 ];
sprintf( str, "Direction: (%3.2f,%3.2f,%3.2f) from %s", dir.fX, dir.fY, dir.fZ, ( facingType == kObject ) ? pRefObject->GetKey()->GetUoid().GetObjectName() : "VCam" );
plDebugText::Instance().DrawString( x, y, str, (UInt32)0xffffffff );
y += 12;
sprintf( str, "Up: (%3.2f,%3.2f,%3.2f) from %s", up.fX, up.fY, up.fZ, ( facingType == kObject ) ? pRefObject->GetKey()->GetUoid().GetObjectName() : "VCam" );
plDebugText::Instance().DrawString( x, y, str, (UInt32)0xffffffff );
y += 12;
sprintf( str, "Position: (%3.2f,%3.2f,%3.2f) from %s", position.fX, position.fY, position.fZ, ( posType == kObject ) ? pRefObject->GetKey()->GetUoid().GetObjectName() : "VCam" );
plDebugText::Instance().DrawString( x, y, str, (UInt32)0xffffffff );
y += 12;
sprintf( str, "Velocity: (%3.2f,%3.2f,%3.2f) from %s", velocity.fX, velocity.fY, velocity.fZ, ( velType == kObject ) ? pRefObject->GetKey()->GetUoid().GetObjectName() : "VCam" );
plDebugText::Instance().DrawString( x, y, str, (UInt32)0xffffffff );
y += 12;
}
plgDispatch::MsgSend( msg );
return true;
}
void plListener::ISetRef( const plKey &ref, hsBool binding, int type )
{
if( binding )
hsgResMgr::ResMgr()->AddViaNotify( ref, TRACKED_NEW plGenRefMsg( GetKey(), plGenRefMsg::kOnReplace, -1, type ), plRefFlags::kPassiveRef );
else
GetKey()->Release( ref );
}
void plListener::IEnsureVCamValid( void )
{
if( fPosRatio == 1.f && fFacingRatio == 1.f && fVelRatio == 1.f )
{
// All of our params are purely using objects, so we don't need a virtual camera pointer at all
if( fVCam != nil )
ISetRef( fVCam->GetKey(), false, kRefVCam );
}
else
{
// One or more of our params are using the vcam as a basis, so make sure we have it
if( fVCam == nil )
{
plVirtualCam1 *vCam = plVirtualCam1::Instance();
if( vCam == nil )
{
hsAssert( false, "Unable to grab virtual camera instance; no basis for listener!!!" );
return;
}
ISetRef( vCam->GetKey(), true, kRefVCam );
}
}
}
void plListener::ICheckAudio( void ) const
{
if( ( fPosRatio < 1.f || fFacingRatio < 1.f || fVelRatio < 1.f ) && fVCam == nil )
plgAudioSys::SetMuted( true );
}
hsBool plListener::MsgReceive(plMessage* msg)
{
plSetListenerMsg *setMsg = plSetListenerMsg::ConvertNoRef( msg );
if( setMsg != nil )
{
hsBool useVCam;
if( setMsg->GetType() & plSetListenerMsg::kVCam )
{
// Reset any ratios
if( setMsg->GetType() & plSetListenerMsg::kPosition )
fPosRatio = 0.f;
if( setMsg->GetType() & plSetListenerMsg::kVelocity )
fVelRatio = 0.f;
if( setMsg->GetType() & plSetListenerMsg::kFacing )
fFacingRatio = 0.f;
IEnsureVCamValid();
}
else
{
useVCam = setMsg->IsBinding();
if( setMsg->GetType() & plSetListenerMsg::kPosition )
fPosRatio = 1.f;
if( setMsg->GetType() & plSetListenerMsg::kVelocity )
fVelRatio = 1.f;
if( setMsg->GetType() & plSetListenerMsg::kFacing )
fFacingRatio = 1.f;
if( fPosRatio > 0.f || fVelRatio > 0.f || fFacingRatio > 0.f )
// Need this, so store it now
ISetRef( setMsg->GetSrcKey(), setMsg->IsBinding(), kRefObject );
}
return true;
}
plEvalMsg* pEMsg = plEvalMsg::ConvertNoRef(msg);
if (pEMsg)
{
IEval(pEMsg->GetTimeStamp(), pEMsg->DelSeconds(), true);
if( fInitMe )
{
// By default, position and orientation are camera based
plSetListenerMsg *set = TRACKED_NEW plSetListenerMsg( plSetListenerMsg::kVCam | plSetListenerMsg::kFacing, nil, true );
set->Send();
set = TRACKED_NEW plSetListenerMsg( plSetListenerMsg::kVCam | plSetListenerMsg::kPosition, nil, true );
set->Send();
fInitMe = false;
}
return true;
}
plGenRefMsg* refMsg = plGenRefMsg::ConvertNoRef( msg );
if( refMsg != nil )
{
if( refMsg->fType == kRefVCam )
{
if( refMsg->GetContext() & ( plRefMsg::kOnCreate | plRefMsg::kOnRequest | plRefMsg::kOnReplace ) )
{
fVCam = plVirtualCam1::ConvertNoRef( refMsg->GetRef() );
}
else if( refMsg->GetContext() & ( plRefMsg::kOnRemove | plRefMsg::kOnDestroy ) )
{
if( plVirtualCam1::ConvertNoRef( refMsg->GetRef() ) == fVCam )
fVCam = nil;
}
ICheckAudio();
}
return true;
}
return plSingleModifier::MsgReceive(msg);
}

View File

@ -0,0 +1,82 @@
/*==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 plListener_h
#define plListener_h
#include "../pnModifier/plSingleModifier.h"
class plSceneObject;
class plVirtualCam1;
class plListener : public plSingleModifier
{
public:
plListener() : fVCam(nil), fInitMe(true){;}
~plListener(){;}
CLASSNAME_REGISTER( plListener );
GETINTERFACE_ANY( plListener, plSingleModifier );
virtual hsBool MsgReceive(plMessage* msg);
static void ShowDebugInfo( hsBool s ) { fPrintDbgInfo = s; }
// Get info for which object these things are attached to - camera or refObject
UInt8 GetAttachedPosType() { return (UInt8)fPosRatio; }
UInt8 GetAttachedFacingType() { return (UInt8)fFacingRatio; }
UInt8 GetAttachedVelType() { return (UInt8)fVelRatio; }
enum
{
kCamera = 0,
kAvatar = 1
};
protected:
enum Refs
{
kRefObject,
kRefVCam
};
plVirtualCam1* fVCam;
hsScalar fPosRatio, fFacingRatio, fVelRatio; // 0 is vCam, 1 is refObject
hsBool fInitMe;
static hsBool fPrintDbgInfo;
virtual hsBool IEval(double secs, hsScalar del, UInt32 dirty);
void ISetRef( const plKey &ref, hsBool binding, int type );
void ICheckAudio( void ) const;
void IEnsureVCamValid( void );
};
#endif //plWin32Sound_h

View File

@ -0,0 +1,415 @@
/*==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 "plRandomSoundMod.h"
#include "../pnSceneObject/plSceneObject.h"
#include "../pnSceneObject/plAudioInterface.h"
#include "../pnMessage/plSoundMsg.h"
#include "../plMessage/plAnimCmdMsg.h"
#include "../plAudio/plAudioSystem.h"
#include "../plAudio/plSound.h"
#include "../plAudio/plWin32GroupedSound.h" // EEK BAD
#include "plgDispatch.h"
#include "hsTimer.h"
#include "../plStatusLog/plStatusLog.h"
plRandomSoundModGroup::plRandomSoundModGroup() : fNumSounds(0), fIndices(nil), fGroupedIdx(-1), fCurrent(-1)
{
}
plRandomSoundModGroup::~plRandomSoundModGroup()
{
delete [] fIndices;
}
void plRandomSoundModGroup::Read(hsStream *s)
{
fNumSounds = s->ReadSwap16();
fGroupedIdx = s->ReadSwap16();
fIndices = TRACKED_NEW UInt16[fNumSounds];
int i;
for (i = 0; i < fNumSounds; i++)
fIndices[i] = s->ReadSwap16();
}
void plRandomSoundModGroup::Write(hsStream *s)
{
s->WriteSwap16(fNumSounds);
s->WriteSwap16(fGroupedIdx);
int i;
for (i = 0; i < fNumSounds; i++)
s->WriteSwap16(fIndices[i]);
}
///////////////////////////////////////////////////////////////////////////////////////
plRandomSoundMod::plRandomSoundMod() : fCurrentGroup(0), fNumGroups(0), fGroups(nil), fOldPriority(-1), fFirstTimePlay(true)
{
}
plRandomSoundMod::~plRandomSoundMod()
{
delete [] fGroups;
}
void plRandomSoundMod::IPlayNextIfMaster()
{
if( !fTarget )
IRetry(2.f);
if( IStopped() )
return;
IPlayNext();
}
// If we recieve a stop message, actually stop the sound
void plRandomSoundMod::IStop()
{
plRandomCommandMod::IStop();
plAudioInterface *ai = nil;
if( !plgAudioSys::Active() ) return;
ai = IGetTargetAudioInterface(0);
if(!ai) return;
if( fGroups != nil && fGroups[ fCurrentGroup ].fGroupedIdx != -1 )
{
plSoundMsg *msg = TRACKED_NEW plSoundMsg();
msg->SetCmd(plSoundMsg::kStop);
msg->fIndex = fGroups[ fCurrentGroup ].fIndices[ fCurrent ];
plgDispatch::MsgSend(msg);
}
else
{
if(fCurrent == -1) return;
UInt16 currentSndIdx = ( fGroups != nil ) ? fGroups[fCurrentGroup].fIndices[fCurrent] : fActiveList[fCurrent];
plSoundMsg* snd = TRACKED_NEW plSoundMsg(GetKey(), GetTarget()->GetKey(), nil);
snd->SetCmd(plSoundMsg::kStop);
snd->fIndex = currentSndIdx;
plgDispatch::MsgSend(snd);
}
}
void plRandomSoundMod::IPlayNext()
{
if( !plgAudioSys::Active() )
{
IRetry(10.f);
return;
}
plAudioInterface* ai = IGetTargetAudioInterface(0);
if( !ai )
{
IRetry(2.f);
return;
}
int i;
UInt16 currentSndIdx;
int nSounds = (fGroups == nil ? ai->GetNumSounds() : fGroups[fCurrentGroup].fNumSounds);
fEndTimes.ExpandAndZero(nSounds);
plSound *pSound = nil;
// The global sound priority has changed, update the active random sounds list
if(fOldPriority != plgAudioSys::GetPriorityCutoff() && fGroups == nil)
{
fActiveList.clear();
fOldPriority = plgAudioSys::GetPriorityCutoff();
for(i = 0; i < nSounds; i++)
{
pSound = ai->GetSound(i);
if(pSound && pSound->GetPriority() <= plgAudioSys::GetPriorityCutoff())
{
fActiveList.push_back(i);
}
}
// There are no sounds that should play
if(fGroups == nil && fActiveList.empty() && nSounds)
{
// If no sounds in this component even attempt to play this component gets mad and will never play any sounds again.
// So, give it a zero to make it happy. This sound will still be rejected when it tries to play which is exactly what
// we want since if we get here no sounds in this component should play.
fActiveList.push_back(0);
}
}
// if this is the first time this component is going to play a sound check to see if it has a delay time
if(fFirstTimePlay)
{
fFirstTimePlay = false;
if( !(fMode & kOneCmd) )
{
hsScalar delay = IGetDelay(0);
double t = hsTimer::GetSysSeconds() + delay;
plAnimCmdMsg* anim = TRACKED_NEW plAnimCmdMsg(GetKey(), GetKey(), &t);
anim->SetCmd(plAnimCmdMsg::kContinue);
plgDispatch::MsgSend(anim);
return;
}
}
if( !ISelectNext(fGroups == nil ? fActiveList.size() : nSounds) )
{
plRandomCommandMod::IStop();
return;
}
// We don't want random sounds to synch, since we don't synch the randomness. So force this next
// sound to not synch
hsScalar currLen;
if( fGroups != nil && fGroups[ fCurrentGroup ].fGroupedIdx != -1 )
{
currentSndIdx = fGroups[ fCurrentGroup ].fIndices[ fCurrent ];
plWin32GroupedSound *sound = plWin32GroupedSound::ConvertNoRef( ai->GetSound( fGroups[ fCurrentGroup ].fGroupedIdx ) );
if (!sound)
{
hsAssert( sound != nil, "Invalid sound type in plRandomSoundMod" );
return;
}
sound->SetLocalOnly(true);
// Send msg to the grouped sound to switch sounds
plSoundMsg *snd = TRACKED_NEW plSoundMsg();
snd->SetCmd( plSoundMsg::kSelectFromGroup );
snd->fIndex = currentSndIdx;
snd->Send( sound->GetKey() );
// Now tell the audio interface to play the sound (probably should change this....)
snd = TRACKED_NEW plSoundMsg(GetKey(), GetTarget()->GetKey(), nil);
snd->SetCmd(plSoundMsg::kGoToTime);
snd->fTime = (0);
snd->SetCmd(plSoundMsg::kStop);
snd->SetCmd(plSoundMsg::kPlay);
snd->fIndex = fGroups[ fCurrentGroup ].fGroupedIdx;
plgDispatch::MsgSend(snd);
currLen = sound->GetSoundLength( currentSndIdx );
}
else
{
currentSndIdx = ( fGroups != nil ) ? fGroups[fCurrentGroup].fIndices[fCurrent] : fActiveList[fCurrent];
if (ai->GetSound(currentSndIdx))
{
ai->GetSound( currentSndIdx )->SetLocalOnly(true);
ai->GetSound(currentSndIdx)->Stop();
ai->GetSound(currentSndIdx)->Play();
}
if (ai->GetSound(currentSndIdx))
currLen = (hsScalar)(ai->GetSound(currentSndIdx)->GetLength());
else
currLen = 0;
}
if (plgAudioSys::AreExtendedLogsEnabled())
{
if (fGroups)
plStatusLog::AddLineS("audio.log", "%s: Playing sound #%d from group %d", GetTarget(0)->GetKeyName(), fCurrent, fCurrentGroup);
else
plStatusLog::AddLineS("audio.log", "%s: Playing sound #%d", GetTarget(0)->GetKeyName(), fCurrent);
}
fEndTimes[fCurrent] = hsTimer::GetSysSeconds() + currLen;
if( !(fMode & kOneCmd) )
{
hsScalar delay = IGetDelay(currLen);
double t = hsTimer::GetSysSeconds() + delay;
plAnimCmdMsg* anim = TRACKED_NEW plAnimCmdMsg(GetKey(), GetKey(), &t);
anim->SetCmd(plAnimCmdMsg::kContinue);
plgDispatch::MsgSend(anim);
}
else
{
plRandomCommandMod::IStop();
}
}
void plRandomSoundMod::SetCurrentGroup(UInt16 group)
{
hsAssert(group < fNumGroups, "Setting an invalid group on a random sound modifier");
if (group != fCurrentGroup && group < fNumGroups)
{
fGroups[fCurrentGroup].fExcluded = fExcluded;
fGroups[fCurrentGroup].fCurrent = fCurrent;
fExcluded = fGroups[group].fExcluded;
fCurrent = fGroups[group].fCurrent;
fCurrentGroup = group;
}
}
void plRandomSoundMod::Read(hsStream *s, hsResMgr *mgr)
{
plRandomCommandMod::Read(s, mgr);
fNumGroups = s->ReadSwap16();
if (fNumGroups > 0)
{
fGroups = TRACKED_NEW plRandomSoundModGroup[fNumGroups];
int i;
for (i = 0; i < fNumGroups; i++)
fGroups[i].Read(s);
}
}
void plRandomSoundMod::Write(hsStream *s, hsResMgr *mgr)
{
plRandomCommandMod::Write(s, mgr);
s->WriteSwap16(fNumGroups);
if (fNumGroups > 0)
{
int i;
for (i = 0; i < fNumGroups; i++)
fGroups[i].Write(s);
}
}
void plRandomSoundMod::ForceSoundLoadState( hsBool loaded )
{
UInt16 i, j;
plAudioInterface* ai = IGetTargetAudioInterface(0);
if( ai == nil )
return;
if( fGroups != nil )
{
for( i = 0; i < fNumGroups; i++ )
{
if( fGroups[ i ].fGroupedIdx != -1 )
{
plSound *sound = ai->GetSound( fGroups[ i ].fGroupedIdx );
if (!sound)
return;
if( loaded )
sound->ForceLoad();
else
sound->ForceUnload();
}
else
{
for( j = 0; j < fGroups[ i ].fNumSounds; j++ )
{
plSound *sound = ai->GetSound( fGroups[ i ].fIndices[ j ] );
if (!sound)
return;
if( loaded )
sound->ForceLoad();
else
sound->ForceUnload();
}
}
}
}
else
{
for( i = 0; i < ai->GetNumSounds(); i++ )
{
plSound *sound = ai->GetSound( i );
if (!sound)
return;
if( loaded )
sound->ForceLoad();
else
sound->ForceUnload();
}
}
}
// Overload this to handle volume changes
hsBool plRandomSoundMod::MsgReceive(plMessage* msg)
{
plAnimCmdMsg* anim = plAnimCmdMsg::ConvertNoRef(msg);
if( anim )
{
// Actually sets the volume
if( anim->Cmd(plAnimCmdMsg::kSetSpeed) )
{
ISetVolume(anim->fSpeed);
}
}
// Don't understand, pass on to base class.
return plRandomCommandMod::MsgReceive(msg);
}
void plRandomSoundMod::ISetVolume(hsScalar volume)
{
plSound *pSound = nil;
pSound = IGetSoundPtr();
if(pSound)
pSound->SetVolume(volume);
}
float plRandomSoundMod::GetVolume()
{
float volume = 1.0;
plSound *pSound;
pSound = IGetSoundPtr();
if(pSound)
volume = pSound->GetMaxVolume();
return volume;
}
void plRandomSoundMod::ISetPosition(hsPoint3 pos)
{
plSound *pSound = IGetSoundPtr();
if(pSound)
{
pSound->SetPosition(pos);
}
}
plSound *plRandomSoundMod::IGetSoundPtr()
{
plSound *pSound = nil;
if(fGroups != nil) return nil;
if(fCurrent == -1) return nil; // sound list hasn't been initialized yet, don't try and access it
int currentSndIdx = fActiveList[fCurrent];
plAudioInterface* ai = IGetTargetAudioInterface(0);
if( !ai )
return nil;
pSound = ai->GetSound( currentSndIdx );
return pSound;
}

View File

@ -0,0 +1,89 @@
/*==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 plRandomSoundMod_inc
#define plRandomSoundMod_inc
#include "../pfAnimation/plRandomCommandMod.h"
class plSound;
struct hsPoint3;
class plRandomSoundModGroup
{
public:
hsBitVector fExcluded;
Int8 fCurrent;
UInt16 fNumSounds;
UInt16 *fIndices;
Int16 fGroupedIdx; // Only used if we point to a groupedSound, in which case fIndices are indices into
// that sound. -1 if unused.
plRandomSoundModGroup();
~plRandomSoundModGroup();
void Read(hsStream *s);
void Write(hsStream *s);
};
class plRandomSoundMod : public plRandomCommandMod
{
protected:
UInt16 fCurrentGroup;
UInt16 fNumGroups;
plRandomSoundModGroup *fGroups;
std::vector<UInt16> fActiveList; // list of sounds we're allowed to choose
int fOldPriority; // old sound priority
hsBool fFirstTimePlay;
virtual void IPlayNext();
virtual void IPlayNextIfMaster();
virtual void IStop();
void ISetVolume(hsScalar volume);
void ISetPosition(hsPoint3);
plSound *IGetSoundPtr();
public:
plRandomSoundMod();
~plRandomSoundMod();
CLASSNAME_REGISTER( plRandomSoundMod );
GETINTERFACE_ANY( plRandomSoundMod, plRandomCommandMod );
virtual void Read(hsStream* s, hsResMgr* mgr);
virtual void Write(hsStream* s, hsResMgr* mgr);
void SetCurrentGroup(UInt16 group);
void ForceSoundLoadState( hsBool loaded );
hsBool MsgReceive(plMessage* msg);
float GetVolume();
// EXPORT ONLY
void SetGroupInfo(UInt16 numGroups, plRandomSoundModGroup *groups) { fNumGroups = numGroups; fGroups = groups; }
};
#endif // plRandomSoundMod_inc

View File

@ -0,0 +1,32 @@
/*==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 plCCRCreatable_inc
#define plCCRCreatable_inc
#include "plCCRMgr.h"
#endif // plCCRCreatable_inc

View File

@ -0,0 +1,31 @@
/*==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 "plCCRMgrBase.h"
#include "plCCRMgr.h"
// static
plCCRMgrBase* plCCRMgrBase::fBaseInstance=nil;

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 plCCRMgr_h
#define plCCRMgr_h
//
// Implementation for CCR commands
//
#include "hsTypes.h"
// Error constants and conversion are outside of the CCR_RELEASE define,
// So that non-CCR code can report CCR errors, and the plCCRMgr can
// share this code.
namespace plCCRError
{
enum Errors
{
kError = hsFail,
kNotAuthorized = -2,
kNilLocalAvatar = -3,
kCCRAlreadyAllocated = -4,
kNetworkingIsDisabled = -5,
kCantFindPlayer = -6,
kInvalidLevel = -7,
kPlayerNotInAge = -8,
kVaultTimedOut = -9,
kVaultFetchFailed = -10,
kAuthTimedOut = -11
};
}
#endif // plCCRMgr_h

View File

@ -0,0 +1,25 @@
/*==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==*/

View File

@ -0,0 +1,30 @@
/*==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 plCCRVault_h
#define plCCRVault_h
#endif // plCCRVault_h

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 pfCameraCreatable_inc
#define pfCameraCreatable_inc
#include "../pnFactory/plCreatable.h"
#include "plCameraBrain.h"
REGISTER_CREATABLE( plCameraBrain1 );
REGISTER_CREATABLE( plCameraBrain1_Drive );
REGISTER_CREATABLE( plCameraBrain1_Avatar );
REGISTER_CREATABLE( plCameraBrain1_FirstPerson);
REGISTER_CREATABLE( plCameraBrain1_Fixed );
REGISTER_CREATABLE( plCameraBrain1_Circle );
#include "plCameraModifier.h"
REGISTER_CREATABLE( plCameraModifier1 );
#include "plInterestingModifier.h"
REGISTER_CREATABLE( plInterestingModifier );
#include "plVirtualCamNeu.h"
REGISTER_CREATABLE( plVirtualCam1 );
#endif // pfCameraCreatable_inc

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==*/
#include "hsTypes.h"
#include "pfCameraProxy.h"
#include "plVirtualCamNeu.h"
#include "../plDrawable/plDrawableGenerator.h"
#include "../pnMessage/plProxyDrawMsg.h"
#include "../plScene/plSceneNode.h"
plCameraProxy::plCameraProxy()
: plProxyGen(hsColorRGBA().Set(0.2f,0.2f,0.8f,1.f), hsColorRGBA().Set(1.f,0.5f,0.5f,1.f), 0.2f),
fOwner(nil), node(nil)
{
}
plCameraProxy::~plCameraProxy()
{
}
hsBool plCameraProxy::Init(plVirtualCam1* aud)
{
plProxyGen::Init(aud);
fOwner = aud;
fProxyMsgType = plProxyDrawMsg::kCamera;
return fOwner != nil;
}
plKey plCameraProxy::IGetNode() const
{
if (node)
return node->GetKey();
return nil;
}
plDrawableSpans* plCameraProxy::ICreateProxy(hsGMaterial* mat, hsTArray<UInt32>& idx, plDrawableSpans* addTo)
{
if( fOwner )
{
// return fOwner->CreateProxy(mat, idx, addTo);
}
return nil;
}

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 plCameraProxy_inc
#define plCameraProxy_inc
#include "../plDrawable/plProxyGen.h"
class plVirtualCam1;
class plSceneNode;
class plCameraProxy : public plProxyGen
{
protected:
plVirtualCam1* fOwner;
virtual plDrawableSpans* ICreateProxy(hsGMaterial* mat, hsTArray<UInt32>& idx, plDrawableSpans* addTo=nil);
virtual plKey IGetNode() const;
public:
plCameraProxy();
virtual ~plCameraProxy();
hsBool Init(plVirtualCam1* aud);
plSceneNode* node;
};
#endif // plCameraProxy_inc

View File

@ -0,0 +1,390 @@
/*==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 plCameraBrain_inc
#define plCameraBrain_inc
#include "../pnKeyedObject/hsKeyedObject.h"
#include "hsMatrix44.h"
#include "hsBitVector.h"
#include "hsTemplates.h"
class plMessage;
class plCameraModifier1;
class plSceneObject;
class plRailCameraMod;
class plCameraBrain1 : public hsKeyedObject
{
public:
enum
{
kCutPos = 0,
kCutPosOnce,
kCutPOA,
kCutPOAOnce,
kAnimateFOV,
kFollowLocalAvatar,
kPanicVelocity,
kRailComponent,
kSubject,
kCircleTarget,
kMaintainLOS,
kZoomEnabled,
kIsTransitionCamera,
kWorldspacePOA,
kWorldspacePos,
kCutPosWhilePan,
kCutPOAWhilePan,
kNonPhys,
kNeverAnimateFOV,
kIgnoreSubworldMovement,
kFalling,
kRunning,
kVerticalWhenFalling,
kSpeedUpWhenRunning,
kFallingStopped,
kBeginFalling,
};
plCameraBrain1(plCameraModifier1* pMod);
plCameraBrain1();
~plCameraBrain1();
CLASSNAME_REGISTER( plCameraBrain1 );
GETINTERFACE_ANY( plCameraBrain1, hsKeyedObject );
void SetCamera(plCameraModifier1* pMod) { fCamera = pMod; }
void SetAccel (hsScalar f) { fAccel = f; }
void SetDecel (hsScalar f) { fDecel = f; }
void SetVelocity (hsScalar f) { fVelocity = f; }
void SetPOAAccel (hsScalar f) { fPOAAccel = f; }
void SetPOADecel (hsScalar f) { fPOADecel = f; }
void SetPOAVelocity (hsScalar f) { fPOAVelocity = f; }
const plCameraModifier1* GetCamera() { return fCamera; }
virtual void Update(hsBool forced = false);
virtual hsBool MsgReceive(plMessage* msg);
virtual plSceneObject* GetSubject();
virtual void SetSubject(plSceneObject* sub);
virtual hsVector3 GetPOAOffset() { return fPOAOffset; }
void SetPOAOffset(hsVector3 pt) { fPOAOffset = pt; }
void AddTarget();
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
virtual hsBool GetFaded() { return false; }
virtual hsBool SetFaded(hsBool b) { return false; }
hsBool HasMovementFlag(int f) { return fMoveFlags.IsBitSet(f); }
void SetMovementFlag(int f);
void ClearMovementFlag(int which) { fMoveFlags.ClearBit( which ); }
void SetFlags(int i) { fFlags.SetBit(i); }
void ClearFlags(int which) { fFlags.ClearBit( which ); }
hsBool HasFlag(int f) { return fFlags.IsBitSet(f); }
void SetGoal(hsPoint3 pt) { fGoal = pt; }
void SetPOAGoal(hsPoint3 pt) { fPOAGoal = pt; }
void SetFOVGoal(hsScalar h, double t);
void SetZoomParams(hsScalar max, hsScalar min, hsScalar rate);
void SetXPanLimit(hsScalar x) {fXPanLimit = x;}
void SetZPanLimit(hsScalar y) {fZPanLimit = y;}
hsScalar GetXPanLimit() {return fXPanLimit;}
hsScalar GetZPanLimit() {return fZPanLimit;}
void SetRail(plRailCameraMod* m) { fRail = m; }
hsPoint3 GetGoal() { return fGoal; }
hsPoint3 GetPOAGoal() { return fPOAGoal; }
virtual void Push(hsBool recenter = true);
virtual void Pop();
hsScalar GetVelocity() { return fVelocity; }
hsScalar GetAccel() { return fAccel; }
hsScalar GetDecel() { return fDecel; }
hsScalar GetPOAAccel() { return fPOAAccel; }
hsScalar GetPOAVelocity() { return fPOAVelocity; }
hsScalar GetPOADecel() { return fPOADecel; }
hsScalar GetCurrentCamSpeed() { return fCurCamSpeed; }
hsScalar GetCurrentViewSpeed() { return fCurViewSpeed; }
void SetCurrentCamSpeed(hsScalar s) { fCurCamSpeed = s; }
void SetCurrentViewSpeed(hsScalar s) { fCurViewSpeed = s; }
hsMatrix44 GetTargetMatrix() { return fTargetMatrix; }
static hsScalar fFallVelocity;
static hsScalar fFallAccel;
static hsScalar fFallDecel;
static hsScalar fFallPOAVelocity;
static hsScalar fFallPOAAccel;
static hsScalar fFallPOADecel;
protected:
virtual void AdjustForInput(double secs);
void IMoveTowardGoal(double time);
void IPointTowardGoal(double time);
void IAnimateFOV(double time);
void IAdjustVelocity(hsScalar adjAccelRate,
hsScalar adjDecelRate,
hsVector3* dir,
hsVector3* vel,
hsScalar maxSpeed,
hsScalar distToGoal,
double elapsedTime);
hsScalar IClampVelocity(hsVector3* vel, hsScalar maxSpeed, double elapsedTime);
hsBool IShouldDecelerate(hsScalar decelSpeed, hsScalar curSpeed, hsScalar distToGoal);
plCameraModifier1* fCamera;
plKey fSubjectKey;
plRailCameraMod* fRail;
hsScalar fCurCamSpeed;
hsScalar fCurViewSpeed;
double fLastTime;
hsScalar fVelocity;
hsScalar fAccel;
hsScalar fDecel;
hsScalar fPOAVelocity;
hsScalar fPOAAccel;
hsScalar fPOADecel;
hsVector3 fPOAOffset;
hsPoint3 fGoal;
hsPoint3 fPOAGoal;
hsScalar fXPanLimit;
hsScalar fZPanLimit;
hsScalar fPanSpeed;
hsScalar fFOVGoal;
double fFOVStartTime;
double fFOVEndTime;
hsScalar fFOVAnimRate;
hsScalar fZoomRate;
hsScalar fZoomMax;
hsScalar fZoomMin;
hsBitVector fMoveFlags;
hsBitVector fFlags;
hsMatrix44 fTargetMatrix;
hsScalar fOffsetLength;
hsScalar fOffsetPct;
double fFallTimer;
};
class plControlEventMsg;
class plCameraBrain1_Drive : public plCameraBrain1
{
protected:
hsPoint3 fDesiredPosition;
hsPoint3 fFacingTarget;
hsBool bUseDesiredFacing;
hsScalar deltaX;
hsScalar deltaY;
hsBool bDisregardY; // these are here to prevent
hsBool bDisregardX; // the camera from jumping when the mouse cursor recenters / wraps around.
hsVector3 fUp;
public:
plCameraBrain1_Drive();
plCameraBrain1_Drive(plCameraModifier1* pMod);
~plCameraBrain1_Drive();
static SetSensitivity(hsScalar f) { fTurnRate = f; }
CLASSNAME_REGISTER( plCameraBrain1_Drive );
GETINTERFACE_ANY( plCameraBrain1_Drive, plCameraBrain1 );
virtual void Update(hsBool forced = false);
virtual hsBool MsgReceive(plMessage* msg);
virtual void Push(hsBool recenter = true);
virtual void Pop();
static hsScalar fAcceleration;
static hsScalar fDeceleration;
static hsScalar fMaxVelocity;
static hsScalar fTurnRate;
};
class plCameraBrain1_Avatar : public plCameraBrain1
{
public:
plCameraBrain1_Avatar();
plCameraBrain1_Avatar(plCameraModifier1* pMod);
~plCameraBrain1_Avatar();
CLASSNAME_REGISTER( plCameraBrain1_Avatar );
GETINTERFACE_ANY( plCameraBrain1_Avatar, plCameraBrain1 );
virtual void Update(hsBool forced = false);
virtual hsBool MsgReceive(plMessage* msg);
virtual void CalculatePosition();
hsVector3 GetOffset() { return fOffset; }
void SetOffset(hsVector3 pt) { fOffset = pt; }
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
virtual hsBool GetFaded() { return fFaded; }
virtual hsBool SetFaded(hsBool b) { fFaded = b; return true; }
virtual void Pop();
virtual void Push(hsBool recenter = true);
protected:
void ISendFadeMsg(hsBool fade);
void IHandleObstacle();
hsPoint3 fHitPoint;
hsVector3 fOffset;
hsVector3 fHitNormal;
hsBool bObscured;
hsBool fFaded;
plSceneObject* fObstacle;
};
class plCameraBrain1_FirstPerson : public plCameraBrain1_Avatar
{
public:
plCameraBrain1_FirstPerson();
plCameraBrain1_FirstPerson(plCameraModifier1* pMod);
~plCameraBrain1_FirstPerson();
CLASSNAME_REGISTER( plCameraBrain1_FirstPerson );
GETINTERFACE_ANY( plCameraBrain1_FirstPerson, plCameraBrain1_Avatar );
virtual void CalculatePosition();
virtual void Push(hsBool recenter = true);
virtual void Pop();
virtual hsBool MsgReceive(plMessage* msg);
// for console hack
static hsBool fDontFade;
protected:
plSceneObject* fPosNode;
};
class plCameraBrain1_Fixed : public plCameraBrain1
{
public:
plCameraBrain1_Fixed();
plCameraBrain1_Fixed(plCameraModifier1* pMod);
~plCameraBrain1_Fixed();
CLASSNAME_REGISTER( plCameraBrain1_Fixed );
GETINTERFACE_ANY( plCameraBrain1_Fixed, plCameraBrain1 );
void SetTargetPoint(plCameraModifier1* pt) { fTargetPoint = pt; }
virtual void Update(hsBool forced = false);
void CalculatePosition();
virtual hsBool MsgReceive(plMessage* msg);
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
private:
plCameraModifier1* fTargetPoint;
};
//
// circle cam brain
//
class plCameraBrain1_Circle : public plCameraBrain1_Fixed
{
public:
enum CircleFlags
{
kLagged = 0x01,
kAbsoluteLag = (0x02 | kLagged),
kFarthest = 0x04,
kTargetted = 0x08,
kHasCenterObject = 0x10,
kPOAObject = 0x20,
kCircleLocalAvatar = 0x40,
};
protected:
UInt32 fCircleFlags;
hsPoint3 fCenter;
plSceneObject* fCenterObject; // optional, use instead of fCenter
hsScalar fRadius;
hsScalar fCurRad, fGoalRad; // Radians
plSceneObject* fPOAObj; // in this case the subject is who we stay close to/away from
hsScalar fCirPerSec;
hsPoint3 IGetClosestPointOnCircle(const hsPoint3* toThisPt);
public:
plCameraBrain1_Circle();
plCameraBrain1_Circle(plCameraModifier1* pMod);
~plCameraBrain1_Circle();
CLASSNAME_REGISTER( plCameraBrain1_Circle );
GETINTERFACE_ANY( plCameraBrain1_Circle, plCameraBrain1_Fixed );
virtual void Read(hsStream *stream, hsResMgr* mgr);
virtual void Write(hsStream *stream, hsResMgr* mgr);
virtual hsPoint3 MoveTowardsFromGoal(const hsPoint3* fromGoal, double secs, hsBool warp = false);
virtual void Update(hsBool forced = false);
virtual hsBool MsgReceive(plMessage* msg);
UInt32 GetCircleFlags() { return fCircleFlags; }
hsPoint3* GetCenter() { return &fCenter; } // use GetCenterPoint
hsPoint3 GetCenterPoint();
hsScalar GetRadius() { return fRadius; }
plSceneObject* GetCenterObject() { return fCenterObject; }
void SetCircumferencePerSec(hsScalar h) { fCirPerSec = h; }
void SetCircleFlags(UInt32 f) { fCircleFlags|=f; }
void SetCenter(hsPoint3* ctr) { fCenter = *ctr; } // Circle lies in the plane z = ctr->z
void SetRadius(hsScalar radius) { fRadius = radius; }
void SetFarCircleCam(hsBool farType) { if (farType) fCircleFlags |= kFarthest; else fCircleFlags &= ~kFarthest; }
void SetCenterObjectKey(plKey k);
void SetPOAObject(plSceneObject* pObj) { fPOAObj = pObj; }
};
#endif

View File

@ -0,0 +1,478 @@
/*==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 "HeadSpin.h"
#include "plCameraModifier.h"
#include "plCameraBrain.h"
#include "plVirtualCamNeu.h"
#include "hsTimer.h"
#include "plgDispatch.h"
#include "../pnSceneObject/plSceneObject.h"
#include "../pnSceneObject/plCoordinateInterface.h"
#include "../plMessage/plInputEventMsg.h"
#include "../plMessage/plAnimCmdMsg.h"
#include "../pnMessage/plTimeMsg.h"
#include "../pnKeyedObject/plKey.h"
#include "../pnKeyedObject/plFixedKey.h"
#include "../plInputCore/plInputDevice.h"
#include "../plInputCore/plInputManager.h"
#include "hsResMgr.h"
#include "../pnMessage/plCameraMsg.h"
#include "../plPhysical/plSimDefs.h"
#include "plPhysical.h"
#include "../pnSceneObject/plSimulationInterface.h"
#include "../plAvatar/plAvatarMgr.h"
#include "../plAvatar/plArmatureMod.h"
#include "../plAvatar/plAvCallbackAction.h"
// new stuff
plCameraModifier1::plCameraModifier1() :
fBrain(nil),
fSubObj(nil),
fFOVw(45.0f),
fFOVh(33.75f),
fAnimated(false),
fStartAnimOnPush(false),
fStopAnimOnPop(false),
fResetAnimOnPop(false),
fInSubLastUpdate(false),
fUpdateBrainTarget(false)
{
fFrom.Set(0,0,0);
fAt.Set(0,1,0);
}
plCameraModifier1::~plCameraModifier1()
{
int i;
for (i = 0; i < GetNumTrans(); i++)
delete(GetTrans(i));
fTrans.SetCountAndZero(0);
for (i = 0; i < fMessageQueue.Count(); i++)
hsRefCnt_SafeUnRef(fMessageQueue[i]);
fMessageQueue.SetCountAndZero(0);
for (i = 0; i < fFOVInstructions.Count(); i++)
hsRefCnt_SafeUnRef(fFOVInstructions[i]);
fFOVInstructions.SetCountAndZero(0);
}
void plCameraModifier1::AddTarget(plSceneObject* so)
{
fTarget = so;
if( plVirtualCam1::Instance() )
plVirtualCam1::Instance()->AddCameraLoaded(so);
fFrom = (so->GetWorldToLocal().GetTranslate());
if (GetBrain())
{
if (fTarget->GetCoordinateInterface())
GetBrain()->AddTarget();
else
fUpdateBrainTarget = true; // update the brain later
}
if (GetKey())
{
plgDispatch::Dispatch()->RegisterForExactType(plEvalMsg::Index(), GetKey());
}
}
void plCameraModifier1::SetSubject(plSceneObject* pObj)
{
if (GetBrain())
GetBrain()->SetSubject(pObj);
else
fSubObj = pObj;
}
plSceneObject* plCameraModifier1::GetSubject()
{
if (GetBrain())
return GetBrain()->GetSubject();
else
return fSubObj;
}
void plCameraModifier1::SetFOVw(hsScalar f, hsBool fUpdateVCam)
{
fFOVw = f;
if (plVirtualCam1::Instance() && fUpdateVCam)
plVirtualCam1::SetFOV(fFOVw, fFOVh, this);
}
void plCameraModifier1::SetFOVh(hsScalar f, hsBool fUpdateVCam)
{
fFOVh = f;
if (plVirtualCam1::Instance() && fUpdateVCam)
plVirtualCam1::SetFOV(fFOVw, fFOVh, this);
}
hsBool plCameraModifier1::SetFaded(hsBool b)
{
if (GetBrain())
return GetBrain()->SetFaded(b);
return false;
}
hsBool plCameraModifier1::GetFaded()
{
if (GetBrain())
return GetBrain()->GetFaded();
return false;
}
hsBool plCameraModifier1::MsgReceive(plMessage* msg)
{
if (GetBrain())
GetBrain()->MsgReceive(msg);
plCameraMsg* pCamMsg = plCameraMsg::ConvertNoRef(msg);
if (pCamMsg)
{
if (pCamMsg->Cmd(plCameraMsg::kAddFOVKeyframe))
{
hsRefCnt_SafeRef(msg);
fFOVInstructions.Append(pCamMsg);
return true;
}
else
if (pCamMsg->Cmd(plCameraMsg::kSetAnimated))
{
fAnimated = true;
return true;
}
}
plEventCallbackMsg* pEventMsg = plEventCallbackMsg::ConvertNoRef(msg);
if (pEventMsg)
{
double time = (double)fFOVInstructions[pEventMsg->fIndex]->GetConfig()->fAccel;
double time2 = (double)pEventMsg->fEventTime;
time = hsABS(time - time2);
hsScalar h = fFOVInstructions[pEventMsg->fIndex]->GetConfig()->fFOVh;
if (GetBrain())
GetBrain()->SetFOVGoal(h, time);
}
plAnimCmdMsg* pAnimMsg = plAnimCmdMsg::ConvertNoRef(msg);
if (pAnimMsg)
{
hsRefCnt_SafeRef(msg);
msg->ClearReceivers();
msg->AddReceiver(msg->GetSender());
fMessageQueue.Append(msg);
return true;
}
plGenRefMsg* pRefMsg = plGenRefMsg::ConvertNoRef(msg);
if (pRefMsg )
{
if( pRefMsg->GetContext() & (plRefMsg::kOnCreate | plRefMsg::kOnRequest) )
{
if (pRefMsg->fType == kRefBrain)
{
plCameraBrain1* pBrain = plCameraBrain1::ConvertNoRef(pRefMsg->GetRef());
if (pBrain)
{
pBrain->SetCamera(this);
fBrain = pBrain;
if (fSubObj)
fBrain->SetSubject(fSubObj);
}
}
else
if (pRefMsg->fType == kRefCallbackMsg && fMessageQueue[pRefMsg->fWhich] != nil)
{
plgDispatch::MsgSend(fMessageQueue[pRefMsg->fWhich]);
fMessageQueue[pRefMsg->fWhich] = nil;
}
}
else if( pRefMsg->GetContext() & (plRefMsg::kOnDestroy | plRefMsg::kOnRemove) )
{
plCameraBrain1* pBrain = (plCameraBrain1*)(pRefMsg->GetRef());
if (fBrain == pBrain)
fBrain = nil;
}
return true;
}
return plSingleModifier::MsgReceive(msg);
}
void plCameraModifier1::Update()
{
// update the brain
// this freeze thing is a useful debugging tool...
if (plVirtualCam1::Instance()->freeze)
return;
if (GetBrain())
{
if (fUpdateBrainTarget && fTarget->GetCoordinateInterface()) // if we need to update the brain and the target is loaded
{
fUpdateBrainTarget = false;
GetBrain()->AddTarget(); // update the brain's target
}
hsBool moveInSub = !(GetBrain()->HasFlag(plCameraBrain1::kIgnoreSubworldMovement));
if (moveInSub && GetBrain()->GetSubject())
{
plKey worldKey = nil;
// First check if this is a physical. If so, grab the subworld from that
if (GetBrain()->GetSubject()->GetSimulationInterface())
{
plPhysical* phys = GetBrain()->GetSubject()->GetSimulationInterface()->GetPhysical();
if (phys)
worldKey = phys->GetWorldKey();
}
// Also, check if this is an avatar. They don't have physicals, you
// have to ask the avatar controller for the subworld key.
if (!worldKey)
{
plArmatureMod* armMod = plAvatarMgr::FindAvatar(plKey(GetBrain()->GetSubject()->GetKey()));
if (armMod && armMod->GetController() )
worldKey = armMod->GetController()->GetSubworld();
}
if (worldKey)
{
// this picks up and moves the camera to it's previous subworld coordinate (so the subworld isn't moving out from underneath us)
hsMatrix44 l2w, w2l;
plSceneObject* so = plSceneObject::ConvertNoRef(worldKey->ObjectIsLoaded());
if (so)
{
l2w = so->GetLocalToWorld();
w2l = so->GetWorldToLocal();
if (fInSubLastUpdate)
{
if (!(fLastSubPos == fFrom && fLastSubPOA == fAt))
{
SetTargetPos(l2w * fLastSubPos);
SetTargetPOA(l2w * fLastSubPOA);
}
}
else
{
fInSubLastUpdate = true;
}
GetBrain()->Update();
fLastSubPos = w2l * GetTargetPos();
fLastSubPOA = w2l * GetTargetPOA();
}
return;
}
else
{
fInSubLastUpdate = false;
}
}
GetBrain()->Update();
fLastSubPos = GetTargetPos();
fLastSubPOA = GetTargetPOA();
}
}
void plCameraModifier1::Read(hsStream* stream, hsResMgr* mgr)
{
hsKeyedObject::Read(stream, mgr);
fBrain = nil;
mgr->ReadKeyNotifyMe(stream, TRACKED_NEW plGenRefMsg(GetKey(), plRefMsg::kOnCreate, 0, kRefBrain), plRefFlags::kActiveRef);
int count = stream->ReadSwap32();
int i;
for (i = 0; i < count; i++)
{
plKey key = mgr->ReadKey(stream);
hsBool cutpos = stream->ReadBool();
hsBool cutpoa = stream->ReadBool();
hsBool ignore = stream->ReadBool();
hsScalar v = stream->ReadSwapScalar();
hsScalar a = stream->ReadSwapScalar();
hsScalar d = stream->ReadSwapScalar();
hsScalar pV = stream->ReadSwapScalar();
hsScalar pA = stream->ReadSwapScalar();
hsScalar pD = stream->ReadSwapScalar();
CamTrans* camTrans = TRACKED_NEW CamTrans(key);
camTrans->fAccel = a;
camTrans->fDecel = d;
camTrans->fVelocity = v;
camTrans->fPOAAccel = pA;
camTrans->fPOADecel = pD;
camTrans->fPOAVelocity = pV;
camTrans->fCutPos = cutpos;
camTrans->fCutPOA = cutpoa;
camTrans->fIgnore = ignore;
fTrans.Append(camTrans);
}
fFOVw = stream->ReadSwapFloat();
fFOVh = stream->ReadSwapFloat();
int n = stream->ReadSwap32();
fMessageQueue.SetCountAndZero(n);
for(i = 0; i < n; i++ )
{
plMessage* pMsg = plMessage::ConvertNoRef(mgr->ReadCreatable(stream));
fMessageQueue[i] = pMsg;
}
for(i = 0; i < n; i++ )
{
mgr->ReadKeyNotifyMe(stream, TRACKED_NEW plGenRefMsg(GetKey(), plRefMsg::kOnCreate, i, kRefCallbackMsg), plRefFlags::kActiveRef);
}
n = stream->ReadSwap32();
fFOVInstructions.SetCountAndZero(n);
for(i = 0; i < n; i++ )
{
plCameraMsg* pMsg = plCameraMsg::ConvertNoRef(mgr->ReadCreatable(stream));
fFOVInstructions[i] = pMsg;
}
fAnimated = stream->ReadBool();
fStartAnimOnPush = stream->ReadBool();
fStopAnimOnPop = stream->ReadBool();
fResetAnimOnPop = stream->ReadBool();
}
void plCameraModifier1::Write(hsStream* stream, hsResMgr* mgr)
{
hsKeyedObject::Write(stream, mgr);
if (fBrain)
mgr->WriteKey(stream, fBrain );
int i = fTrans.Count();
stream->WriteSwap32(i);
for (i = 0; i < fTrans.Count(); i++)
{
mgr->WriteKey(stream, fTrans[i]->fTransTo);
stream->WriteBool(fTrans[i]->fCutPos);
stream->WriteBool(fTrans[i]->fCutPOA);
stream->WriteBool(fTrans[i]->fIgnore);
stream->WriteSwapScalar(fTrans[i]->fVelocity);
stream->WriteSwapScalar(fTrans[i]->fAccel);
stream->WriteSwapScalar(fTrans[i]->fDecel);
stream->WriteSwapScalar(fTrans[i]->fPOAVelocity);
stream->WriteSwapScalar(fTrans[i]->fPOAAccel);
stream->WriteSwapScalar(fTrans[i]->fPOADecel);
}
stream->WriteSwapFloat(fFOVw);
stream->WriteSwapFloat(fFOVh);
stream->WriteSwap32(fMessageQueue.Count());
for (i = 0; i < fMessageQueue.Count(); i++)
{
mgr->WriteCreatable(stream, fMessageQueue[i]);
}
for (i = 0; i < fMessageQueue.Count(); i++)
{
mgr->WriteKey(stream, fMessageQueue[i]->GetSender());
}
stream->WriteSwap32(fFOVInstructions.Count());
for (i = 0; i < fFOVInstructions.Count(); i++)
{
mgr->WriteCreatable(stream, fFOVInstructions[i]);
}
stream->WriteBool(fAnimated);
stream->WriteBool(fStartAnimOnPush);
stream->WriteBool(fStopAnimOnPop);
stream->WriteBool(fResetAnimOnPop);
}
void plCameraModifier1::Push(hsBool recenter)
{
if (fAnimated)
{
if (fStartAnimOnPush)
{
plAnimCmdMsg* pMsg = TRACKED_NEW plAnimCmdMsg;
pMsg->SetCmd(plAnimCmdMsg::kRunForward);
pMsg->SetBCastFlag(plMessage::kPropagateToModifiers);
pMsg->AddReceiver(GetTarget()->GetKey());
if (GetBrain() && GetBrain()->GetSubject())
pMsg->AddReceiver(GetBrain()->GetSubject()->GetKey());
pMsg->Send();
}
}
if (fBrain)
fBrain->Push(recenter);
if (GetKey())
{
plgDispatch::Dispatch()->RegisterForExactType(plMouseEventMsg::Index(), GetKey());
}
}
void plCameraModifier1::Pop()
{
if (fAnimated)
{
if (fStopAnimOnPop)
{
plAnimCmdMsg* pMsg = TRACKED_NEW plAnimCmdMsg;
pMsg->SetCmd(plAnimCmdMsg::kStop);
pMsg->SetBCastFlag(plMessage::kPropagateToModifiers);
pMsg->AddReceiver(GetTarget()->GetKey());
if (GetBrain() && GetBrain()->GetSubject())
pMsg->AddReceiver(GetBrain()->GetSubject()->GetKey());
pMsg->Send();
}
if (fResetAnimOnPop)
{
plAnimCmdMsg* pMsg = TRACKED_NEW plAnimCmdMsg;
pMsg->SetCmd(plAnimCmdMsg::kGoToBegin);
pMsg->SetBCastFlag(plMessage::kPropagateToModifiers);
pMsg->AddReceiver(GetTarget()->GetKey());
if (GetBrain() && GetBrain()->GetSubject())
pMsg->AddReceiver(GetBrain()->GetSubject()->GetKey());
pMsg->Send();
}
}
if (fBrain)
fBrain->Pop();
if (GetKey()) // the reason we might not have a key is a special run-time POA which doesn't need to receive messages...
{
plgDispatch::Dispatch()->UnRegisterForExactType(plMouseEventMsg::Index(), GetKey());
}
}
void plCameraModifier1::SetTransform(hsPoint3 at)
{
if (!GetTarget())
return;
hsMatrix44 l2w;
hsMatrix44 w2l;
hsVector3 up(0,0,1);
l2w.Make(&fFrom, &at, &up);
l2w.GetInverse(&w2l);
IGetTargetCoordinateInterface(0)->SetTransform( l2w, w2l );
}

View File

@ -0,0 +1,157 @@
/*==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 plCameraModifier_inc
#define plCameraModifier_inc
#include "../pnModifier/plSingleModifier.h"
#include "hsBitVector.h"
#include "hsGeometry3.h"
#include "hsTemplates.h"
class plPipeline;
class plKey;
class plCameraBrain1;
class plCameraMsg;
struct CamTrans
{
// used when creating default track transitions at runtime
CamTrans(plKey to)
{
fTransTo = to;
fAccel = 60.0f;
fDecel = 60.0f;
fVelocity = 60.0f;
fPOADecel = 60.0f;
fPOAAccel = 60.0f;
fPOAVelocity = 60.0f;
fCutPos = false;
fCutPOA = false;
fIgnore = false;
}
plKey fTransTo;
hsBool fCutPos;
hsBool fCutPOA;
hsBool fIgnore;
hsScalar fAccel;
hsScalar fDecel;
hsScalar fVelocity;
hsScalar fPOAAccel;
hsScalar fPOADecel;
hsScalar fPOAVelocity;
};
class plCameraModifier1 : public plSingleModifier
{
enum
{
kRefBrain,
kRefCut,
kRefTrack,
kRefCallbackMsg,
};
protected:
void Output();
virtual hsBool IEval(double secs, hsScalar del, UInt32 dirty) { return true; }
public:
plCameraModifier1();
virtual ~plCameraModifier1();
CLASSNAME_REGISTER( plCameraModifier1 );
GETINTERFACE_ANY( plCameraModifier1, plSingleModifier );
virtual hsBool MsgReceive(plMessage* msg);
void Initialize();
virtual void Update();
virtual void AddTarget(plSceneObject* so);
void SetBrain(plCameraBrain1* brain) { fBrain = brain; }
plCameraBrain1* GetBrain() { return fBrain;}
hsPoint3 GetTargetPos() { return fFrom; }
hsPoint3 GetTargetPOA() { return fAt; }
hsPoint3 GetSubworldPos() { return fLastSubPos; }
hsPoint3 GetSubworldPOA() { return fLastSubPOA; }
void SetTransform(hsPoint3 at);
void SetTargetPos(hsPoint3 pos) { fFrom = pos; }
void SetTargetPOA(hsPoint3 pos) { fAt = pos; }
void SetSubworldPos(hsPoint3 pos) { fLastSubPos = pos; }
void SetSubworldPOA(hsPoint3 pos) { fLastSubPOA = pos; }
hsScalar GetFOVw() { return fFOVw; }
hsScalar GetFOVh() { return fFOVh; }
void SetFOVw(hsScalar f, hsBool fUpdateVCam = true);
void SetFOVh(hsScalar f, hsBool fUpdateVCam = true);
hsBool GetInSubworld() { return fInSubLastUpdate; }
void InSubworld(hsBool b) { fInSubLastUpdate = b; }
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
void AddTrans(CamTrans* t) { fTrans.Append(t); }
int GetNumTrans() { return fTrans.Count(); }
CamTrans* GetTrans(int i) { return fTrans[i]; }
void SetSubject(plSceneObject* pObj);
plSceneObject* GetSubject();
virtual void Push(hsBool recenter = true);
virtual void Pop();
virtual hsBool GetFaded();
virtual hsBool SetFaded(hsBool b);
hsBool IsAnimated() { return fAnimated; }
void SetAnimCommands(hsBool a, hsBool b, hsBool c) { fStartAnimOnPush = a; fStopAnimOnPop = b; fResetAnimOnPop = c; }
private:
hsPoint3 fFrom;
hsPoint3 fAt;
plCameraBrain1* fBrain; // the 'logic' portion of the camera
hsTArray<CamTrans*> fTrans;
plSceneObject* fSubObj;
hsScalar fFOVw;
hsScalar fFOVh;
hsTArray<plMessage*> fMessageQueue;
hsTArray<plCameraMsg*> fFOVInstructions;
hsBool fAnimated, fStartAnimOnPush, fStopAnimOnPop, fResetAnimOnPop;
hsPoint3 fLastSubPos;
hsPoint3 fLastSubPOA;
hsBool fInSubLastUpdate;
hsBool fUpdateBrainTarget; // sometimes our target isn't loaded yet, so wait to update the brain til later
};
#endif plCameraModifier_inc

View File

@ -0,0 +1,72 @@
/*==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 "../plMessage/plInterestingPing.h"
#include "hsBounds.h"
#include "plInterestingModifier.h"
#include "../pnSceneObject/plSceneObject.h"
#include "../pnMessage/plTimeMsg.h"
#include "../pnKeyedObject/plKey.h"
hsScalar plInterestingModifier::fInterestRadius = 100.0f;
hsScalar plInterestingModifier::fInterestWeight = 1.0f;
hsBool plInterestingModifier::IEval(double secs, hsScalar del, UInt32 dirty)
{
for (int i=0; i < GetNumTargets(); i++)
{
if( GetTarget(i) && GetTarget(i)->GetDrawInterface() )
{
const hsBounds3Ext& targBnd = GetTarget(i)->GetDrawInterface()->GetWorldBounds();
if( targBnd.GetType() == kBoundsNormal )
{
plInterestingModMsg* pMsg = TRACKED_NEW plInterestingModMsg;
pMsg->fPos= GetTarget(i)->GetDrawInterface()->GetWorldBounds().GetCenter();
pMsg->fSize = GetTarget(i)->GetDrawInterface()->GetWorldBounds().GetMaxDim();
pMsg->fRadius = fInterestRadius;
pMsg->fWeight = fInterestWeight;
pMsg->fObj = GetTarget(i)->GetKey();
pMsg->fType = GetType();
pMsg->SetBCastFlag( plMessage::kPropagateToModifiers );
plgDispatch::MsgSend( pMsg );
}
}
}
return true;
}
void plInterestingModifier::AddTarget(plSceneObject* so)
{
fTarget = so;
plgDispatch::Dispatch()->RegisterForExactType(plEvalMsg::Index(), GetKey());
}

View File

@ -0,0 +1,79 @@
/*==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 plInterestingModifier_inc
#define plInterestingModifier_inc
#include "../pnModifier/plSingleModifier.h"
#include "../pnMessage/plMessage.h"
#include "hsResMgr.h"
#include "hsGeometry3.h"
#include "hsStream.h"
class plInputEventMsg;
class plInterestingModifier : public plSingleModifier
{
protected:
enum
{
kTypeInteresting = 0,
kTypeLookAtMod,
};
UInt8 fType;
hsScalar fView;
static hsScalar fInterestRadius;
static hsScalar fInterestWeight;
virtual hsBool IEval(double secs, hsScalar del, UInt32 dirty);
public:
plInterestingModifier(){ fType = kTypeInteresting;}
virtual ~plInterestingModifier(){;}
virtual hsBool MsgReceive(plMessage* msg) {return false;}
CLASSNAME_REGISTER( plInterestingModifier );
GETINTERFACE_ANY( plInterestingModifier, plSingleModifier );
hsScalar GetInterestWeight() { return fInterestWeight; }
hsScalar GetInterestRadius() { return fInterestRadius; }
void SetInterestWeight(hsScalar _InterestRadius) { fInterestWeight =_InterestRadius; }
void SetInterestRadius(hsScalar _InterestWeight) { fInterestRadius =_InterestWeight; }
virtual void AddTarget(plSceneObject* so);
void SetType(UInt8 type) { fType = type; }
UInt8 GetType() { return fType; }
};
#endif plInterestingModifier_inc

View File

@ -0,0 +1,235 @@
/*==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 plVirtualCam1_inc
#define plVirtualCam1_inc
#include "../pnKeyedObject/hsKeyedObject.h"
#include "hsMatrix44.h"
#include "hsBitVector.h"
class plPipeline;
class plCameraModifier1;
class plCameraBrain1;
class plSceneObject;
class plKey;
class hsGMaterial;
class plDrawableSpans;
class plCameraProxy;
class plSceneNode;
class plDebugInputInterface;
class plPlate;
#include "hsTemplates.h"
struct CamTrans;
struct hsColorRGBA;
#define POS_TRANS_OFF 0
#define POS_TRANS_FIXED 1
#define POS_TRANS_FOLLOW 2
#define POA_TRANS_OFF 3
#define POA_TRANS_FIXED 4
#define POA_TRANS_FOLLOW 5
class plVirtualCam1 : public hsKeyedObject
{
protected:
void Output();
void IUpdate();
void INext();
public:
enum flags
{
kSetFOV,
kCutNextTrans,
kRender,
kRegionIgnore,
kFirstPersonEnabled,
kResponderForced3rd,
kScriptsForced3rd,
kScriptsDisabled1st,
kAvatarWalking,
kUnPanCamera,
kInterpPanLimits,
kFalling,
//kRegisteredForBehaviors, // not reliable anymore since we have a dummy avatar in the startup age
kFirstPersonAtLinkOut,
kJustLinkedIn,
kFirstPersonUserSelected,
};
enum action
{
kPush = 0,
kPop,
kReplacement,
kBackgroundPop,
kRefCamera,
};
plVirtualCam1();
virtual ~plVirtualCam1();
CLASSNAME_REGISTER( plVirtualCam1 );
GETINTERFACE_ANY( plVirtualCam1, hsKeyedObject );
void SetPipeline(plPipeline* p);
void Init();
virtual hsBool MsgReceive(plMessage* msg);
static void SetFOV(hsScalar w, hsScalar h);
static void SetFOV(hsScalar w, hsScalar h, plCameraModifier1* pCam);
static void SetDepth(hsScalar h, hsScalar y);
static hsScalar GetFOVw() { return fFOVw; }
static hsScalar GetFOVh() { return fFOVh; }
static hsScalar GetHither() { return fHither; }
static hsScalar GetYon() { return fYon; }
static void SetOffset(float x, float y, float z);
static void SetAspectRatio(float aspect) { fAspectRatio = aspect; }
static float GetAspectRatio() { return fAspectRatio; }
hsBool InTransition() { return fTransPos != POS_TRANS_OFF; }
plCameraModifier1* GetCurrentCamera();
plCameraModifier1* GetCurrentStackCamera();
plCameraModifier1* GetTransitionCamera(){return fTransitionCamera;}
hsBool Is1stPersonCamera();
hsBool HasMovementFlag(int f) { return fMoveFlags.IsBitSet(f); }
void SetMovementFlag(int f, hsBool on = true) { fMoveFlags.SetBit(f, on);}
hsPoint3 GetCameraPos() { return fOutputPos; }
hsPoint3 GetCameraPOA() { return fOutputPOA; }
hsVector3 GetCameraUp() { return fOutputUp; }
void SetCutNextTrans(); // used when player warps into a new camera region
const hsMatrix44 GetCurrentMatrix() { return fMatrix; }
static plVirtualCam1* Instance() { return fInstance; }
int GetNumCameras() { return fCameraStack.Count(); }
plCameraModifier1* GetCameraNumber(int camNumber);
void RebuildStack(const plKey& key);
void SetFlags(int flag) { fFlags.SetBit(flag); }
hsBool HasFlags(int flag) { return fFlags.IsBitSet(flag); }
void ClearFlags(int flag) { fFlags.ClearBit(flag); }
// console command stuff
static void Next();
static void Prev();
static void Deactivate();
void CameraRegions(hsBool b) { fFlags.SetBit(kRegionIgnore,b); }
void LogFOV(hsBool b) { printFOV = b; }
void Drive();
void PushThirdPerson();
static void AddMsgToLog(const char* msg);
static hsBool IsCurrentCamera(const plCameraModifier1* mod);
void ClearStack();
void AddCameraLoaded(plSceneObject* pCam) { fCamerasLoaded.Append(pCam); }
hsBool RestoreFromName(const char* name);
void StartUnPan();
// these are for console access
static hsBool fUseAccelOverride, freeze, alwaysCutForColin, WalkPan3rdPerson,StayInFirstPersonForever;
static hsScalar fDecel, fAccel, fVel;
static hsScalar fFallTimerDelay;
private:
void Reset(hsBool bRender);
void PushCamera(plCameraModifier1* pCam, hsBool bDefault = false);
void PopCamera(plCameraModifier1* pCam);
void AddCameraToStack(plCameraModifier1* pCam);
void PopAll();
void CreateDefaultCamera(plSceneObject* subject);
void StartTransition(CamTrans* transition);
void RunTransition();
void FinishTransition();
void SetRender(hsBool render);
void IHandleCameraStatusLog(plCameraModifier1* pMod, int action);
void ICreatePlate();
void FreezeOutput(int frames) { fFreezeCounter = frames; } // I hate this and I hate myself for doing it
void UnFadeAvatarIn(int frames) { fFadeCounter = frames; } // ditto
void FirstPersonOverride();
void AdjustForInput();
void UnPanIfNeeded();
void StartInterpPanLimits();
void InterpPanLimits();
plPipeline* fPipe;
hsMatrix44 fMatrix;
hsPoint3 fOutputPos;
hsPoint3 fOutputPOA;
hsVector3 fOutputUp;
int fTransPos;
plDebugInputInterface* fCameraDriveInterface;
plPlate* fEffectPlate;
FILE* foutLog;
hsTArray<plCameraModifier1*> fCameraStack;
int fFreezeCounter;
int fFadeCounter;
hsBitVector fFlags;
hsTArray<plSceneObject*> fCamerasLoaded;
hsBitVector fMoveFlags;
hsScalar fX;
hsScalar fY;
hsScalar fXPanLimit;
hsScalar fZPanLimit;
hsScalar fXPanLimitGoal;
hsScalar fZPanLimitGoal;
hsScalar fXUnPanRate;
hsScalar fZUnPanRate;
hsScalar fXPanInterpRate;
hsScalar fZPanInterpRate;
double fUnPanEndTime;
double fInterpPanLimitTime;
hsScalar fRetainedFY;
// built-in cameras
plCameraModifier1* fDriveCamera; // for driving around
plCameraModifier1* fTransitionCamera; // transitions between cameras placed in scenes
plCameraModifier1* fPythonOverride; // a special camera pushed by python
plCameraModifier1* fFirstPersonOverride; // the built-in first person camera
plCameraModifier1* fPrevCam; // the last camera we were displaying
plCameraModifier1* fThirdPersonCam; // built in third person cam for ccr's when they jump about
static hsScalar fFOVh, fFOVw;
static hsScalar fHither, fYon;
static plVirtualCam1* fInstance;
static hsBool printFOV;
static hsScalar fPanResponseTime;
static float fAspectRatio;
hsBool fForceCutOnce;
};
#endif plVirtualCam1_inc

View File

@ -0,0 +1,35 @@
/*==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 pfCharacterCreatable_inc
#define pfCharacterCreatable_inc
#include "../pnFactory/plCreator.h"
#include "pfMarkerMgr.h"
REGISTER_NONCREATABLE(pfMarkerMgr);
#endif // pfCharacterCreatable_inc

View File

@ -0,0 +1,250 @@
/*==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 "pfMarkerInfo.h"
#include "pfMarkerMgr.h"
#include "../plModifier/plGameMarkerModifier.h"
#include "../plMessage/plLoadCloneMsg.h"
#include "../pnMessage/plWarpMsg.h"
#include "../pnSceneObject/plCoordinateInterface.h"
#include "../plMessage/plAnimCmdMsg.h"
#include "../pnMessage/plEnableMsg.h"
#include "../pnMessage/plSoundMsg.h"
#include "../pnSceneObject/plAudioInterface.h"
// For Init
#include "../pnMessage/plClientMsg.h"
#include "../pnSceneObject/plSceneObject.h"
#include "../plResMgr/plResManager.h"
#include "../plResMgr/plKeyFinder.h"
plUoid pfMarkerInfo::fMarkerUoid;
static const int kFreezeLen = 10; // How long a marker is frozen after you hit it
void pfMarkerInfo::Init()
{
plResManager* resMgr = (plResManager*)hsgResMgr::ResMgr();
// Force the client to keep the GlobalMarkers keys loaded, so we don't load them every time we clone
plClientMsg* loadAgeKeysMsg = TRACKED_NEW plClientMsg(plClientMsg::kLoadAgeKeys);
loadAgeKeysMsg->SetAgeName("GlobalMarkers");
loadAgeKeysMsg->Send(resMgr->FindKey(kClient_KEY));
//
// Get the Uoid for the markers
//
plLocation markerLoc = plKeyFinder::Instance().FindLocation("GlobalMarkers", "Markers");
if (markerLoc.IsValid())
fMarkerUoid = plUoid(markerLoc, plSceneObject::Index(), "MarkerRoot");
else
fMarkerUoid.Invalidate();
}
pfMarkerInfo::pfMarkerInfo(const hsPoint3& pos, bool isNew) :
fMod(nil),
fPosition(pos),
fType(kMarkerOpen),
fLastChange(0),
fVisible(true),
fIsNew(isNew),
fSpawned(false)
{
}
void pfMarkerInfo::Spawn(MarkerType type)
{
if (!fMarkerUoid.IsValid())
{
plResManager* resMgr = (plResManager*)hsgResMgr::ResMgr();
plLocation markerLoc = plKeyFinder::Instance().FindLocation("GlobalMarkers", "Markers");
if (markerLoc.IsValid())
fMarkerUoid = plUoid(markerLoc, plSceneObject::Index(), "MarkerRoot");
else
{
hsAssert(false, "Unable to spawn markers because the marker age was not loaded or found");
return;
}
}
fType = type;
fLastChange = 0;
plLoadCloneMsg* cloneMsg = TRACKED_NEW plLoadCloneMsg(fMarkerUoid, pfMarkerMgr::Instance()->GetKey(), 0);
cloneMsg->SetBCastFlag(plMessage::kNetPropagate, false);
fKey = cloneMsg->GetCloneKey();
cloneMsg->Send();
}
void pfMarkerInfo::InitSpawned(plKey markerKey)
{
fKey = markerKey;
fSpawned = true;
plSceneObject* so = plSceneObject::ConvertNoRef(fKey->GetObjectPtr());
fMod = (plGameMarkerModifier*)so->GetModifierByType(plGameMarkerModifier::Index());
hsAssert(fMod, "Couldn't find marker modifier");
fMod->FixupAnimKeys();
// Warp it into position
hsMatrix44 pos;
pos.Reset();
pos.SetTranslate(&fPosition);
plWarpMsg* warpMsg = TRACKED_NEW plWarpMsg(pfMarkerMgr::Instance()->GetKey(), fKey, plWarpMsg::kFlushTransform, pos);
warpMsg->Send();
// update its state
Show(fVisible);
IPlayColor(true);
if (fType == kMarkerLocalSelected)
IPlayBounce(true);
}
void pfMarkerInfo::Show(bool show)
{
fVisible = show;
if (fSpawned) {
plEnableMsg* msg = TRACKED_NEW plEnableMsg;
msg->SetBCastFlag(plMessage::kPropagateToChildren);
msg->SetCmd(plEnableMsg::kDrawable);
msg->SetCmd(show ? plEnableMsg::kEnable : plEnableMsg::kDisable);
msg->SetSender(pfMarkerMgr::Instance()->GetKey());
msg->Send(fKey);
}
}
void pfMarkerInfo::SetFrozen(double freezeStartTime)
{
fLastChange = freezeStartTime;
IPlayBounce(true);
}
void pfMarkerInfo::Update(double curTime)
{
if (fLastChange != 0 && (curTime - fLastChange) > kFreezeLen)
{
fLastChange = 0;
IPlayBounce(false);
}
if (fIsNew)
{
IPlaySound(true);
fIsNew = false;
}
}
void pfMarkerInfo::Remove()
{
if (fKey)
{
plLoadCloneMsg* cloneMsg = TRACKED_NEW plLoadCloneMsg(fKey, pfMarkerMgr::Instance()->GetKey(), 0, false);
cloneMsg->SetBCastFlag(plMessage::kNetPropagate, false);
cloneMsg->Send();
fKey = nil;
fMod = nil;
}
}
void pfMarkerInfo::SetType(pfMarkerInfo::MarkerType type)
{
if (fType == kMarkerLocalSelected)
IPlayBounce(false);
IPlayColor(false);
fType = type;
IPlayColor(true);
if (fType == kMarkerLocalSelected)
IPlayBounce(true);
}
void pfMarkerInfo::IPlayBounce(bool play)
{
if (fMod && fSpawned)
{
// Send anim start/stop msg
plAnimCmdMsg* animMsg = TRACKED_NEW plAnimCmdMsg;
animMsg->SetCmd(play ? plAnimCmdMsg::kContinue : plAnimCmdMsg::kStop);
animMsg->SetCmd(plAnimCmdMsg::kSetLooping);
animMsg->SetCmd(plAnimCmdMsg::kGoToBegin);
animMsg->SetSender(pfMarkerMgr::Instance()->GetKey());
animMsg->Send(fMod->fBounceAnimKey);
}
}
void pfMarkerInfo::IPlayColor(bool play)
{
if (fMod && fSpawned)
{
// Play the correct color anim
plKey key = nil;
switch (fType)
{
case kMarkerOpen:
case kMarkerLocal:
case kMarkerLocalSelected:
key = fMod->fOpenAnimKey;
break;
case kMarkerGreen:
key = fMod->fGreenAnimKey;
break;
case kMarkerRed:
key = fMod->fRedAnimKey;
break;
}
plAnimCmdMsg* animMsg = TRACKED_NEW plAnimCmdMsg;
animMsg->SetCmd(play ? plAnimCmdMsg::kContinue : plAnimCmdMsg::kStop);
animMsg->SetCmd(plAnimCmdMsg::kSetLooping);
animMsg->SetCmd(plAnimCmdMsg::kGoToBegin);
animMsg->SetSender(pfMarkerMgr::Instance()->GetKey());
animMsg->AddReceiver(key);
animMsg->Send();
}
}
void pfMarkerInfo::IPlaySound(bool place)
{
if (fMod && fSpawned)
{
const plAudioInterface* ai = fMod->GetTarget()->GetAudioInterface();
plSoundMsg* msg = TRACKED_NEW plSoundMsg;
msg->fIndex = place ? fMod->fPlaceSndIdx : fMod->fHitSndIdx;
msg->SetCmd(plSoundMsg::kPlay);
msg->SetSender(pfMarkerMgr::Instance()->GetKey());
msg->Send(ai->GetKey());
}
}

View File

@ -0,0 +1,84 @@
/*==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 pfMarkerInfo_h_inc
#define pfMarkerInfo_h_inc
#include "../pnKeyedObject/plKey.h"
#include "../pnKeyedObject/plUoid.h"
#include "hsGeometry3.h"
class plMessage;
class plGameMarkerModifier;
class pfMarkerInfo
{
public:
enum MarkerType { kMarkerOpen, kMarkerGreen, kMarkerRed, kMarkerLocal, kMarkerLocalSelected };
protected:
// MarkerMgr will set this up
static plUoid fMarkerUoid;
plKey fKey;
plGameMarkerModifier* fMod;
hsPoint3 fPosition;
MarkerType fType;
double fLastChange; // Last time this marker changed hands
bool fVisible;
bool fIsNew;
bool fSpawned;
void IPlayBounce(bool play);
void IPlayColor(bool play);
void IPlaySound(bool place);
public:
pfMarkerInfo(const hsPoint3& pos, bool isNew);
~pfMarkerInfo() {}
static void Init();
plKey GetKey() { return fKey; }
void Spawn(MarkerType type);
void InitSpawned(plKey markerKey);
void Remove();
void Update(double curTime);
void Show(bool show);
bool IsVisible() { return fVisible; }
void SetType(pfMarkerInfo::MarkerType type);
pfMarkerInfo::MarkerType GetType() { return fType; }
void SetFrozen(double freezeStartTime);
bool IsFrozen() { return fLastChange != 0; }
void PlayHitSound() { IPlaySound(false); }
};
#endif // pfMarkerInfo_h_inc

View File

@ -0,0 +1,313 @@
/*==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 "pfMarkerMgr.h"
#include "../pfMessage/pfMarkerMsg.h"
#include "pfMarkerInfo.h"
#include "../plModifier/plCloneSpawnModifier.h"
#include "../plStatusLog/plStatusLog.h"
#include "../plMessage/plLoadCloneMsg.h"
#include "../pnMessage/plTimeMsg.h"
#include "../pnMessage/plNotifyMsg.h"
#include "../plNetClient/plNetClientMgr.h"
#include "plgDispatch.h"
////////////////////////////////////////////////////////////////////////////////
pfMarkerMgr* pfMarkerMgr::fInstance = nil;
const UInt32 pfMarkerMgr::kNoMarkerSelected = (UInt32)(-1);
pfMarkerMgr* pfMarkerMgr::Instance()
{
if (!pfMarkerMgr::fInstance)
{
pfMarkerMgr::fInstance = TRACKED_NEW pfMarkerMgr;
pfMarkerMgr::fInstance->IInit();
}
return pfMarkerMgr::fInstance;
}
void pfMarkerMgr::Shutdown()
{
if (pfMarkerMgr::fInstance)
{
pfMarkerMgr::fInstance->IShutdown();
pfMarkerMgr::fInstance = nil;
}
}
////////////////////////////////////////////////////////////////////////////////
pfMarkerMgr::pfMarkerMgr(): fSelectedMarker(kNoMarkerSelected), fShowingLocalMarkers(false), fMarkersRespawn(false)
{
fLog = plStatusLogMgr::GetInstance().CreateStatusLog(20, "Marker.log", plStatusLog::kAlignToTop | plStatusLog::kFilledBackground);
pfMarkerInfo::Init();
}
pfMarkerMgr::~pfMarkerMgr()
{
delete fLog;
}
void pfMarkerMgr::IInit()
{
fMyKey = RegisterAs(kMarkerMgr_KEY);
plgDispatch::Dispatch()->RegisterForExactType(plEvalMsg::Index(), GetKey());
}
void pfMarkerMgr::IShutdown()
{
std::map<UInt32, pfMarkerInfo*>::iterator curMarker = fMarkers.begin();
while (curMarker != fMarkers.end())
{
curMarker->second->Remove();
DEL(curMarker->second);
++curMarker;
}
fMarkers.clear();
plgDispatch::Dispatch()->UnRegisterForExactType(plEvalMsg::Index(), GetKey());
UnRegisterAs(kMarkerMgr_KEY);
}
pfMarkerInfo* pfMarkerMgr::IFindMarker(plKey markerKey, UInt32& id)
{
std::map<UInt32, pfMarkerInfo*>::iterator curMarker = fMarkers.begin();
while (curMarker != fMarkers.end())
{
if (curMarker->second->GetKey() == markerKey)
{
id = curMarker->first;
return curMarker->second;
}
++curMarker;
}
id = kNoMarkerSelected;
return nil;
}
void pfMarkerMgr::IUpdate()
{
// Update all markers
std::map<UInt32, pfMarkerInfo*>::iterator curMarker = fMarkers.begin();
while (curMarker != fMarkers.end())
{
curMarker->second->Update(hsTimer::GetSeconds());
++curMarker;
}
}
void pfMarkerMgr::IMarkerHit(plKey markerKey, plKey playerKey)
{
if (playerKey != plNetClientMgr::GetInstance()->GetLocalPlayerKey())
return; // not the local player, abort
// make sure the marker isn't frozen
UInt32 id;
pfMarkerInfo* hitMarker = IFindMarker(markerKey, id);
if (!hitMarker)
return; // abort, something weird is going on
if (hitMarker->IsFrozen())
return; // marker frozen, abort
// tell people about it
pfMarkerMsg* msg = TRACKED_NEW pfMarkerMsg;
msg->fType = pfMarkerMsg::kMarkerCaptured;
msg->fMarkerID = id;
msg->Send();
}
void pfMarkerMgr::AddMarker(double x, double y, double z, UInt32 id, bool justCreated)
{
if (fMarkers.find(id) != fMarkers.end())
{
// delete existing one if we're changing its location
fMarkers[id]->Remove();
DEL(fMarkers[id]);
}
hsPoint3 pos((hsScalar)x, (hsScalar)y, (hsScalar)z);
fMarkers[id] = TRACKED_NEW pfMarkerInfo(pos, justCreated);
fMarkers[id]->Spawn(pfMarkerInfo::kMarkerOpen);
}
void pfMarkerMgr::RemoveMarker(UInt32 id)
{
if (fMarkers.find(id) == fMarkers.end())
return;
fMarkers[id]->Remove();
DEL(fMarkers[id]);
fMarkers.erase(id);
}
void pfMarkerMgr::RemoveAllMarkers()
{
std::map<UInt32, pfMarkerInfo*>::iterator curMarker = fMarkers.begin();
while (curMarker != fMarkers.end())
{
curMarker->second->Remove();
DEL(curMarker->second);
++curMarker;
}
fMarkers.clear();
}
void pfMarkerMgr::ClearSelectedMarker()
{
if (fSelectedMarker != kNoMarkerSelected)
{
if (fMarkers.find(fSelectedMarker) != fMarkers.end())
fMarkers[fSelectedMarker]->SetType(pfMarkerInfo::kMarkerOpen);
fSelectedMarker = kNoMarkerSelected;
}
}
void pfMarkerMgr::SetSelectedMarker(UInt32 id)
{
ClearSelectedMarker();
if (id != kNoMarkerSelected)
{
if (fMarkers.find(id) != fMarkers.end())
{
fMarkers[id]->SetType(pfMarkerInfo::kMarkerLocalSelected);
fSelectedMarker = id;
}
}
}
UInt32 pfMarkerMgr::GetSelectedMarker()
{
return fSelectedMarker;
}
// for QUEST games (no teams)
void pfMarkerMgr::CaptureMarker(UInt32 id, bool captured)
{
if (fMarkers.find(id) == fMarkers.end())
return;
if (fMarkersRespawn)
fMarkers[id]->SetFrozen(hsTimer::GetSeconds());
else
fMarkers[id]->Show(!captured);
fMarkers[id]->PlayHitSound();
fMarkers[id]->SetType(captured ? pfMarkerInfo::kMarkerGreen : pfMarkerInfo::kMarkerOpen);
}
// for TEAM games (0 = not captured)
void pfMarkerMgr::CaptureMarker(UInt32 id, int team)
{
if (fMarkers.find(id) == fMarkers.end())
return;
if (fMarkersRespawn)
fMarkers[id]->SetFrozen(hsTimer::GetSeconds());
else
fMarkers[id]->Show(team == 0); // 0 = uncaptured
fMarkers[id]->PlayHitSound();
if (team == 0)
fMarkers[id]->SetType(pfMarkerInfo::kMarkerOpen);
else if (team == 1)
fMarkers[id]->SetType(pfMarkerInfo::kMarkerGreen);
else
fMarkers[id]->SetType(pfMarkerInfo::kMarkerRed);
}
void pfMarkerMgr::LocalShowMarkers(bool show)
{
fShowingLocalMarkers = show;
if (show)
{
std::map<UInt32, pfMarkerInfo*>::iterator curMarker = fMarkers.begin();
while (curMarker != fMarkers.end())
curMarker->second->Show(true);
}
else
{
std::map<UInt32, pfMarkerInfo*>::iterator curMarker = fMarkers.begin();
while (curMarker != fMarkers.end())
curMarker->second->Show(false);
}
}
bool pfMarkerMgr::AreLocalMarkersShowing()
{
return fShowingLocalMarkers;
}
hsBool pfMarkerMgr::MsgReceive(plMessage* msg)
{
plEvalMsg* evalMsg = plEvalMsg::ConvertNoRef(msg);
if (evalMsg)
{
IUpdate();
return true;
}
// Somebody hit a marker
plNotifyMsg* notify = plNotifyMsg::ConvertNoRef(msg);
if (notify)
{
proCollisionEventData* cEvent = (proCollisionEventData*)notify->FindEventRecord(proEventData::kCollision);
if (cEvent)
{
plKey markerKey = cEvent->fHittee;
plKey playerKey = cEvent->fHitter;
if (plNetClientMgr::GetInstance()->IsAPlayerKey(cEvent->fHittee))
{
// swap the above, since the hittee is actually the player
playerKey = cEvent->fHittee;
markerKey = cEvent->fHitter;
}
IMarkerHit(markerKey, playerKey);
}
return true;
}
plLoadCloneMsg* cloneMsg = plLoadCloneMsg::ConvertNoRef(msg);
if (cloneMsg)
{
plKey cloneKey = cloneMsg->GetCloneKey();
if (cloneMsg->GetIsLoading() && cloneKey)
{
UInt32 id;
pfMarkerInfo* marker = IFindMarker(cloneKey, id);
marker->InitSpawned(cloneKey);
}
return true;
}
return hsKeyedObject::MsgReceive(msg);
}

View File

@ -0,0 +1,97 @@
/*==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 pfMarkerMgr_h_inc
#define pfMarkerMgr_h_inc
#include "../pnKeyedObject/hsKeyedObject.h"
#include <map>
class plStatusLog;
////////////////////////////////////////////////////////////////////////////////
class pfMarkerMsg;
class pfMarkerGame;
class pfMarkerInfo;
class pfMarkerMgr : public hsKeyedObject
{
protected:
friend class pfMarkerInfo;
friend class pfMarkerInfoOwned;
// Because for some reason if I ask for my key, the refs hit zero when I release it (0 initial refs?)
plKey fMyKey;
plStatusLog* fLog;
static pfMarkerMgr* fInstance;
bool fShowingLocalMarkers;
bool fMarkersRespawn;
UInt32 fSelectedMarker;
static const UInt32 kNoMarkerSelected;
std::map<UInt32, pfMarkerInfo*> fMarkers; // key is marker id number
void IInit();
void IShutdown();
pfMarkerInfo* IFindMarker(plKey markerKey, UInt32& id);
void IUpdate();
void IMarkerHit(plKey markerKey, plKey playerKey);
pfMarkerMgr();
~pfMarkerMgr();
public:
CLASSNAME_REGISTER(pfMarkerMgr);
GETINTERFACE_ANY(pfMarkerMgr, hsKeyedObject);
static pfMarkerMgr* Instance();
static void Shutdown();
hsBool MsgReceive(plMessage* msg);
void AddMarker(double x, double y, double z, UInt32 id, bool justCreated);
void RemoveMarker(UInt32 id);
void RemoveAllMarkers();
void ClearSelectedMarker();
void SetSelectedMarker(UInt32 id);
UInt32 GetSelectedMarker();
void SetMarkersRespawn(bool respawn) {fMarkersRespawn = respawn;}
bool GetMarkersRespawn() {return fMarkersRespawn;}
void CaptureMarker(UInt32 id, bool captured); // for QUEST games (no teams)
void CaptureMarker(UInt32 id, int team); // for TEAM games (0 = not captured)
// Shows your markers locally, so you can see where they are
void LocalShowMarkers(bool show = true);
bool AreLocalMarkersShowing();
};
#endif // pfMarkerMgr_h_inc

View File

@ -0,0 +1,610 @@
/*==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==*/
//#pragma warning(disable: 4503 4786)
//#define HK_HARDCORE
//
//#include <hkmath/vector3.h> // for havok Vector3
////#include <.//gpi/math/quaternion.h> // for havok Vector3
//#include <hkgeometry/geomdef.h> // for havok Vertex
//
//
//#include "hsTypes.h"
//#include "../plInterp/plController.h"
//#include "plPlayerModifier.h"
//#include "hsTimer.h"
//#include "../pnSceneObject/plSceneObject.h"
//#include "../pnSceneObject/plSimulationInterface.h"
//#include "../pnInputCore/plControlEventCodes.h"
//#include "../pnMessage/plTimeMsg.h"
//#include "../pnMessage/plWarpMsg.h"
//#include "../pnMessage/plCameraMsg.h"
//#include "../pnSceneObject/plCoordinateInterface.h"
//#include "plgDispatch.h"
//#include "../pfCamera/plCameraModifier.h"
//#include "hsResMgr.h"
//#include "../pnKeyedObject/plKey.h"
//#include "../plNetClient/plNetClientMgr.h"
//#include "../plModifier/plSpawnModifier.h"
//#include "../plMessage/plMatrixUpdateMsg.h"
//
//#include "../pnTimer/plTimerCallbackManager.h"
//#include "../plAudio/plAudioSystem.h"
//#include "../plMessage/plInputEventMsg.h"
//#include "../plMessage/plSpawnRequestMsg.h"
//#include "../plMessage/plSpawnModMsg.h"
//#include "../plMessage/plPlayerMsg.h"
//#include "../pnMessage/plAudioSysMsg.h"
//#include "../pfCamera/plCameraBrain.h"
//
//#include "../plHavok1/plHKPhysical.h"
//
//hsScalar plPlayerModifier::fTurnRate = 1.0f;
//hsScalar plPlayerModifier::fAcceleration = 80.0f;
//hsScalar plPlayerModifier::fDeceleration = 80.0f;
//hsScalar plPlayerModifier::fMaxVelocity = 200.0f;
//
//plPlayerModifier::plPlayerModifier() :
//bUseDesiredFacing(false),
//bUseDesiredMatrix(false)
//{
// fCurSpeed = 0.0f;
// fLastTime = 0.0;
// bMoving = false;
// fRotationScalar = 1.0f;
// bIgnoreDesiredMatrix = false;
// SetFlag( kWantsToSpawn );
//}
//
//plPlayerModifier::~plPlayerModifier()
//{
// for (int i = 0; i < fSpawnPoints.Count(); i++)
// delete fSpawnPoints[i];
// fSpawnPoints.SetCount(0);
//}
//
//// Adding RemoveTarget override of plSingleModifier to tell everyone we
//// told in AddTarget about our subject that he's gone now.
//void plPlayerModifier::RemoveTarget(plSceneObject* so)
//{
// if( fTarget && fTarget->IsLocallyOwned()==plSynchedObject::kYes )
// {
// plCameraMsg* pMsg = TRACKED_NEW plCameraMsg;
// pMsg->SetCmd(plCameraMsg::kSetSubject);
// pMsg->SetSubject(nil);
// pMsg->SetBCastFlag( plMessage::kBCastByExactType );
// plgDispatch::MsgSend(pMsg);
//
// plAudioSysMsg* pAudMsg1 = TRACKED_NEW plAudioSysMsg(plAudioSysMsg::kSetListenerCoordinateRefCamera);
// plAudioSysMsg* pAudMsg2 = TRACKED_NEW plAudioSysMsg(plAudioSysMsg::kSetListenerVelocityRefCamera);
// plAudioSysMsg* pAudMsg3 = TRACKED_NEW plAudioSysMsg(plAudioSysMsg::kSetListenerFacingRefCamera);
// plgDispatch::MsgSend(pAudMsg1);
// plgDispatch::MsgSend(pAudMsg2);
// plgDispatch::MsgSend(pAudMsg3);
// }
// plSingleModifier::RemoveTarget(so);
//}
//
//void plPlayerModifier::AddTarget(plSceneObject* so)
//{
// fTarget = so;
// plSimulationInterface * pSI = IGetTargetSimulationInterface(0); // so->GetSimulationInterface(); //
//
// plgDispatch::Dispatch()->RegisterForExactType(plEvalMsg::Index(), GetKey());
//
// // set the desired rotation vector...
//// hsAssert(fTarget->GetCoordinateInterface(), "Player modifier target has no coordinate interface");
//
// // These are now set in the component
//// if(pSI)
//// {
//// pSI->SetProperty(plSimulationInterface::kAffectLOS, false);
//// pSI->SetProperty(kUpright, true);
//// }
//
// //
// // setup for local player if necessary
// //
// int locallyOwned=so->IsLocallyOwned();
// if (locallyOwned==plSynchedObject::kMaybe) // don't know since we're still loading, defer
// SetFlag(kNeedsLocalSetup);
// else if (locallyOwned==plSynchedObject::kYes)
// IDoLocalSetup(so);
//}
//
//void plPlayerModifier::IDoLocalSetup(plSceneObject* so)
//{
// plCameraMsg* pMsg = TRACKED_NEW plCameraMsg;
// pMsg->SetCmd(plCameraMsg::kSetSubject);
// pMsg->SetSubject(so);
// pMsg->SetBCastFlag( plMessage::kBCastByExactType );
// plgDispatch::MsgSend(pMsg);
//
// // this is to solve the problem of physical vs nonphysical players...
//// plCameraMsg* pMsg2 = TRACKED_NEW plCameraMsg;
//// pMsg2->SetBCastFlag(plMessage::kBCastByExactType);
//// pMsg2->SetCmd(plCameraMsg::kSetOffset);
//// pMsg2->SetCmd(plCameraMsg::kEntering);
//// pMsg2->SetTriggerer(so->GetKey());
//// pMsg2->SetOffsetY(50);
//// pMsg2->SetOffsetZ(10);
//// plgDispatch::MsgSend(pMsg2);
//}
//
//void plPlayerModifier::IMakeUsListener( plSceneObject *so )
//{
// // set the listener to use us...
// plAudioSysMsg* pAudMsg1 = TRACKED_NEW plAudioSysMsg(plAudioSysMsg::kSetListenerFacingRef);
// pAudMsg1->SetSceneObject(so->GetKey());
// plAudioSysMsg* pAudMsg2 = TRACKED_NEW plAudioSysMsg(plAudioSysMsg::kSetListenerCoordinateRef);
// pAudMsg2->SetSceneObject(so->GetKey());
// plAudioSysMsg* pAudMsg3 = TRACKED_NEW plAudioSysMsg(plAudioSysMsg::kSetListenerVelocityRef);
// pAudMsg3->SetSceneObject(so->GetKey());
// plgDispatch::MsgSend(pAudMsg1);
// plgDispatch::MsgSend(pAudMsg2);
// plgDispatch::MsgSend(pAudMsg3);
//
// // Now that we have a valid listener, unmute the audio system
// plgAudioSys::SetMuted( false );
//}
//
//hsBool plPlayerModifier::MsgReceive(plMessage* msg)
//{
// plControlEventMsg* pCommandMsg = plControlEventMsg::ConvertNoRef(msg);
// if (pCommandMsg)
// return(HandleControlInput(pCommandMsg));
//
// plMatrixUpdateMsg* pMMsg = plMatrixUpdateMsg::ConvertNoRef( msg );
// if (pMMsg && HasFlag(kHasSpawned))
// {
// hsAssert(GetTarget()->IsLocallyOwned()==plSynchedObject::kNo, "master objects should not get correction msgs");
// fDesiredMatrix = pMMsg->fMatrix;
// if (bIgnoreDesiredMatrix)
// bIgnoreDesiredMatrix = false;
// else
// {
// bUseDesiredMatrix = true;
// }
// return true;
// }
//
// plSpawnModMsg* pSpawn = plSpawnModMsg::ConvertNoRef(msg);
// if (pSpawn && HasFlag(kWantsToSpawn))
// {
// spawnPt* pt = TRACKED_NEW spawnPt;
// pt->pt = pSpawn->fPos;
//
// hsVector3 temp(fTarget->GetCoordinateInterface()->GetLocalToWorld().GetTranslate() - pt->pt);
// pt->dist = temp.MagnitudeSquared();
// fSpawnPoints.Append(pt);
// }
// plPlayerMsg* pPMsg = plPlayerMsg::ConvertNoRef(msg);
// if (pPMsg)
// {
// if (pPMsg->Cmd(plPlayerMsg::kWarpToSpawnPoint))
// {
// WarpToSpawnPoint();
// return true;
// }
// }
// return plSingleModifier::MsgReceive(msg);
//}
//
//hsBool plPlayerModifier::HandleControlInput(plControlEventMsg* pMsg)
//{
// hsBool ret=false;
//
// if (pMsg->ControlActivated() && (pMsg->GetControlCode() == B_CONTROL_ROTATE_RIGHT || pMsg->GetControlCode() == B_CONTROL_ROTATE_LEFT || pMsg->GetControlCode() == A_CONTROL_TURN))
// {
// fRotationScalar = pMsg->GetPct();
// if ( HasMovementFlag( pMsg->GetControlCode() ) )
// bIgnoreDesiredMatrix = true;
// }
// if (pMsg->ControlActivated() && !HasMovementFlag( pMsg->GetControlCode() ) )
// {
// SetMovementFlag( pMsg->GetControlCode() );
// if ( pMsg->GetControlCode() == B_CONTROL_TURN_TO )
// {
// //fFacingTarget = pMsg->GetTurnToPt();
// }
// }
// else
// if ( !pMsg->ControlActivated() && HasMovementFlag( pMsg->GetControlCode() ) )
// {
// ClearMovementFlag( pMsg->GetControlCode() );
// }
//
// ret = true;
// return ret;
//}
//
//void plPlayerModifier::SetMoving(hsBool b)
//{
// if (b != bMoving)
// {
// plPlayerMsg* pMsg = TRACKED_NEW plPlayerMsg;
//
// if (b)
// pMsg->SetCmd( plPlayerMsg::kMovementStarted );
// else
// pMsg->SetCmd( plPlayerMsg::kMovementStopped );
//
// plgDispatch::MsgSend( pMsg );
// bMoving = b;
// }
//}
//
//
//hsPoint3 forceForward(0,-200,0);
//hsPoint3 forceRight(-200,0,0);
//hsPoint3 forceUp(0,0,15);
//
//hsBool plPlayerModifier::IEval(double secs, hsScalar del, UInt32 dirty)
//{
// // setup for local player if necessary
// if (HasFlag(kNeedsLocalSetup))
// {
// int locallyOwned=fTarget->IsLocallyOwned();
// if (locallyOwned==plSynchedObject::kYes)
// IDoLocalSetup(fTarget);
// else
// if (locallyOwned==plSynchedObject::kNo)
// ClearFlag(kNeedsLocalSetup);
// }
//
// if (HasFlag(kWantsToSpawn))
// {
// if (fTarget->IsLocallyOwned()==plSynchedObject::kNo)
// {
// // if our target is a proxy player, don't warp him to a spawn point;
// // we will receive his location as a state update.
// ClearFlag(kWantsToSpawn);
// }
// else
// if (fSpawnPoints.Count()
// // if MP game, make sure we're connected before spawning
// && (!plNetClientMgr::GetInstance()->IsEnabled() ||
// plNetClientMgr::GetInstance()->HasJoined())
// )
// {
// int i;
//#if 0
// for (i = 0; i < fSpawnPoints.Count(); i++)
// {
// for (int j = i + 1; j < fSpawnPoints.Count(); j++)
// {
// if (fSpawnPoints[j]->dist < fSpawnPoints[i]->dist)
// {
// spawnPt* pt;
// pt = fSpawnPoints[j];
// fSpawnPoints[j] = fSpawnPoints[i];
// fSpawnPoints[i] = pt;
// }
// }
// }
// hsPoint3 warpPoint = fSpawnPoints[0]->pt;
//#else
// // choose spawnPoint based on netID, not distance
// int netID = plNetClientMgr::GetInstance()->GetClientNum();
// if (netID==-1)
// netID=0;
// hsPoint3 warpPoint = netID>=fSpawnPoints.Count() ?
// fSpawnPoints[fSpawnPoints.Count()-1]->pt : fSpawnPoints[netID]->pt;
//#endif
// // Send msg for net synchronization
// plWarpMsg* warpMsg = TRACKED_NEW plWarpMsg;
// warpMsg->fPos = warpPoint;
// warpMsg->AddReceiver( fTarget->GetKey() );
// warpMsg->SetWarpFlags(warpMsg->GetWarpFlags() | plWarpMsg::kFlushTransform | plWarpMsg::kZeroVelocity );
// plgDispatch::MsgSend( warpMsg );
//#ifdef HS_DEBUGGING
// char str[256];
// sprintf(str, "%s has %d spawnPoints. Using pt %f %f %f\n",
// GetKeyName(), fSpawnPoints.GetCount(),
// fSpawnPoints[0]->pt.fX,fSpawnPoints[0]->pt.fY,fSpawnPoints[0]->pt.fZ);
// hsStatusMessage(str);
//#endif
// for (i = 0; i < fSpawnPoints.Count(); i++)
// delete fSpawnPoints[i];
//
// fSpawnPoints.SetCount(0);
// ClearFlag(kWantsToSpawn);
// }
// else
// {
// plSpawnRequestMsg* pMsg = TRACKED_NEW plSpawnRequestMsg;
// pMsg->SetSender(GetKey());
// plgDispatch::MsgSend( pMsg );
// }
// bIgnoreDesiredMatrix = true;
// return true;
// }
// else
// {
// if( !HasFlag( kHasSpawned ) )
// {
// // Don't make us listener until we have actually spawned
// IMakeUsListener( fTarget );
// SetFlag(kHasSpawned);
// }
// }
//
// if (!fTarget->GetCoordinateInterface())
// return true;
//
// // update our desired position:
//// hsScalar eTime = secs - fLastTime;
// hsScalar eTime = hsTimer::GetDelSysSeconds();
//
// hsPoint3 newLinearForce(0,0,0);
//
// hsMatrix44 targetMatrix;
// if (bUseDesiredMatrix)
// targetMatrix = fDesiredMatrix;
// else
// targetMatrix = fTarget->GetCoordinateInterface()->GetLocalToWorld();
// hsPoint3 playerPos = targetMatrix.GetTranslate();
// hsVector3 view, up, right;
// targetMatrix.GetAxis(&view, &up, &right);
//
// hsScalar speed = fMaxVelocity;
// hsScalar turn = fTurnRate;
//
// if (HasMovementFlag(B_CONTROL_MODIFIER_FAST))
// {
// turn *= 0.25;
// speed *= 3.5;
// }
// if (HasMovementFlag(B_CONTROL_MOVE_FORWARD))
// {
// playerPos += view * speed * eTime;
// newLinearForce = newLinearForce + forceForward * speed * eTime; // calc force for physics
// }
// if (HasMovementFlag(B_CONTROL_MOVE_BACKWARD))
// {
// playerPos += view * speed * eTime * -1;
// newLinearForce = newLinearForce + forceForward * speed * eTime * -1; // calc force for physics
// }
// if (HasMovementFlag(B_CONTROL_STRAFE_LEFT))
// {
// playerPos += right * speed * eTime * -1;
//
// newLinearForce = newLinearForce + forceRight * speed * eTime * -1;
// }
// if (HasMovementFlag(B_CONTROL_STRAFE_RIGHT))
// {
// playerPos += right * speed * eTime;
//
// newLinearForce = newLinearForce + forceRight * speed * eTime;
// }
// if (HasMovementFlag(B_CONTROL_MOVE_DOWN))
// {
// playerPos += up * speed * eTime * -1;
//
// newLinearForce = newLinearForce + forceUp * speed * eTime * -1;
// }
// if (HasMovementFlag(B_CONTROL_MOVE_UP))
// {
// playerPos += up * speed * eTime;
//
// newLinearForce = newLinearForce + forceUp * speed * eTime;
// }
//
//
// fDesiredPosition = playerPos;
//
// // move toward our desired position...
//
// hsPoint3 curPos = targetMatrix.GetTranslate();
// hsPoint3 newPos;
//
// hsVector3 dir(fDesiredPosition - curPos);
// hsScalar distToGoal=dir.Magnitude();
//
// if (dir.MagnitudeSquared() > 0.0f)
// dir.Normalize();
//
// hsVector3 vel( view * fCurSpeed );
//
// IAdjustVelocity(fAcceleration, fDeceleration, &dir, &vel, fMaxVelocity, distToGoal, eTime);
// fCurSpeed = vel.Magnitude();
//
// hsScalar distMoved = IClampVelocity(&vel, fMaxVelocity, eTime);
//
// // compute final pos
// if (distMoved > distToGoal)
// newPos = fDesiredPosition;
// else
// newPos = curPos + vel;
//
// // calculate rotation matrix
//
// hsVector3 rotUp(0,0,1);
// hsVector3 rotRight(1,0,0);
// hsMatrix44 rot;
//
// if ( HasMovementFlag( B_CONTROL_TURN_TO ) )
// {
// // compute view goal
//
// hsVector3 fPlayerViewGoal(&fFacingTarget,&curPos);
// fPlayerViewGoal.fZ = 0;
// fPlayerViewGoal.Normalize();
//
// // compute degrees needed to turn left/right
// hsVector3 cross = fPlayerViewGoal % view;
// hsScalar dot = fPlayerViewGoal * view;
// hsScalar rad = hsACosine(dot);
// fRotationScalar = 1.0f;
//
// if (cross.fZ<0)
// {
// SetMovementFlag( B_CONTROL_ROTATE_LEFT );
// }
// else
// {
// SetMovementFlag( B_CONTROL_ROTATE_RIGHT );
// }
// if (dot >= 0.999f)
// {
// ClearMovementFlag( B_CONTROL_TURN_TO );
// ClearMovementFlag( B_CONTROL_ROTATE_RIGHT );
// ClearMovementFlag( B_CONTROL_ROTATE_LEFT );
// }
// }
//
// hsScalar angle = 0;
//
// if ( HasMovementFlag( B_CONTROL_ROTATE_RIGHT ) )
// {
// angle = fTurnRate * eTime * -1 * fRotationScalar;
// }
//
// if ( HasMovementFlag( B_CONTROL_ROTATE_LEFT ) || HasMovementFlag( A_CONTROL_TURN ) )
// {
// angle = fTurnRate * eTime * fRotationScalar;
// }
//
// hsMatrix44 justRot(targetMatrix);
// hsPoint3 zero(0,0,0);
// justRot.SetTranslate(&zero);
//
// if(angle) {
// hsQuat q(angle, &rotUp);
// q.NormalizeIfNeeded();
// q.MakeMatrix(&rot);
//
// justRot = rot * justRot;
//
// targetMatrix = rot * targetMatrix;
// }
//
// // use the desired rotation matrix to set position and rotation:
//
//
// plSimulationInterface * SI = IGetTargetSimulationInterface(0);
//
// if(SI)
// {
// Havok::Vector3 hkLocalForce(newLinearForce.fX, newLinearForce.fY, newLinearForce.fZ);
// if (bUseDesiredMatrix)
// {
// hsMatrix44 inv;
//
// fDesiredMatrix.GetInverse(&inv);
//
// // we're just going to set the position on the simulation interface directly
// // because it will then be further modified by the simulation and its final position
// // will *then* be sent to the coordinate interface
// SI->SetTransform(fDesiredMatrix, inv);
// }
//
// SI->SetRotation(justRot);//rot);
// SI->ApplyForce(plSimulationInterface::kForce, hkLocalForce);
// } else {
// hsMatrix44 inv;
// targetMatrix.SetTranslate(&newPos);
// targetMatrix.GetInverse(&inv);
//
// plCoordinateInterface* pCI = pCI = IGetTargetCoordinateInterface(0);
// pCI->SetTransform(targetMatrix, inv);
//
//
// }
//
// fLastTime = secs;
// SetMoving(fCurSpeed);
//
// if (bUseDesiredMatrix)
// bUseDesiredMatrix = false;
// return true;
//}
//
////
//// vector version. dir vector should be normalized
////
//void plPlayerModifier::IAdjustVelocity(hsScalar adjAccelRate, hsScalar adjDecelRate,
// hsVector3* dir, hsVector3* vel, hsScalar maxSpeed,
// hsScalar distToGoal, double elapsedTime)
//{
// hsScalar speed = vel->Magnitude(); // save current speed
// *vel = *dir * speed; // change vel to correct dir
//
// // compute accel/decel
// hsScalar finalAccelRate;
// if (IShouldDecelerate(adjDecelRate, speed, distToGoal))
// {
// finalAccelRate = -adjDecelRate;
// }
// else
// {
// finalAccelRate = adjAccelRate;
// }
//
// if (finalAccelRate != 0)
// {
// // compute accel vector in the direction of the goal
// hsVector3 accelVec = *dir * finalAccelRate;
// accelVec = accelVec * elapsedTime;
//
// // add acceleration to velocity
// *vel = *vel + accelVec;
// }
// else
// {
// *vel = *dir * maxSpeed;
// }
//}
//
//hsScalar plPlayerModifier::IClampVelocity(hsVector3* vel, hsScalar maxSpeed, double elapsedTime)
//{
// *vel = *vel * elapsedTime;
// maxSpeed *= elapsedTime;
//
// // clamp speed (clamp if going negative?)
// hsScalar distMoved = vel->Magnitude();
// if (distMoved > maxSpeed)
// {
// vel->Normalize();
// *vel = *vel * maxSpeed;
// return maxSpeed;
// }
// return distMoved;
//}
//
//hsBool32 plPlayerModifier::IShouldDecelerate(hsScalar decelSpeed, hsScalar curSpeed, hsScalar distToGoal)
//{
// if (decelSpeed == 0)
// // no deceleration
// return false;
//
// // compute distance required to stop, given decel speed (in units/sec sq)
// hsScalar stopTime = curSpeed / decelSpeed;
// hsScalar avgSpeed = curSpeed * .5f;
// hsScalar stopDist = avgSpeed * stopTime;
//
// return (hsABS(distToGoal) <= hsABS(stopDist)); // stopDist+avgSpeed?
//}
//

View File

@ -0,0 +1,133 @@
/*==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 plPlayerModifier_inc
//#define plPlayerModifier_inc
//
//#include "../pnModifier/plSingleModifier.h"
//#include "../pnSceneObject/plSimulationInterface.h"
//#include "hsMatrix44.h"
//
//class plControlEventMsg;
//
//namespace Havok {
// class Vector3;
//}
//
//class plPlayerModifier : public plSingleModifier
//{
//protected:
//
// enum
// {
// kWantsToSpawn = 0,
// kTimerSet,
// kHasSpawned,
// kNeedsLocalSetup
// };
//
// struct spawnPt
// {
// hsPoint3 pt;
// hsScalar dist;
// };
//
// static hsScalar fTurnRate;
//
// static hsScalar fAcceleration;
// static hsScalar fDeceleration;
// static hsScalar fMaxVelocity;
// hsScalar fCurSpeed;
//
//
// double fLastTime;
// hsMatrix44 fDesiredMatrix;
//
// hsPoint3 fDesiredPosition;
// hsPoint3 fFacingTarget;
// bool bUseDesiredFacing;
// bool bUseDesiredMatrix;
// bool bIgnoreDesiredMatrix;
//
// hsScalar fRotationScalar;
// hsTArray<spawnPt*> fSpawnPoints;
//
// void IAdjustVelocity(hsScalar adjAccelRate,
// hsScalar adjDecelRate,
// hsVector3* dir,
// hsVector3* vel,
// hsScalar maxSpeed,
// hsScalar distToGoal,
// double elapsedTime);
//
// hsScalar IClampVelocity(hsVector3* vel, hsScalar maxSpeed, double elapsedTime);
// hsBool32 IShouldDecelerate(hsScalar decelSpeed, hsScalar curSpeed, hsScalar distToGoal);
//
// hsBool HasMovementFlag(int f) const { return fMoveFlags.IsBitSet(f); }
// void SetMovementFlag(int f) { fMoveFlags.SetBit(f); }
// void ClearMovementFlag(int which) { fMoveFlags.ClearBit( which ); }
//
// hsBitVector fMoveFlags;
// hsBitVector fFlags;
//
// void WarpToSpawnPoint() { SetFlag( kWantsToSpawn ); }
//
// hsBool bMoving;
//
// void IApplyForce(plSimulationInterface::plSimpleForce type, const Havok::Vector3 &vec);
// void IDoLocalSetup(plSceneObject*);
// void IMakeUsListener( plSceneObject *so );
//
//public:
// plPlayerModifier();
// virtual ~plPlayerModifier();
//
// CLASSNAME_REGISTER( plPlayerModifier );
// GETINTERFACE_ANY( plPlayerModifier, plSingleModifier );
//
// virtual hsBool MsgReceive(plMessage* msg);
// virtual void AddTarget(plSceneObject* so);
// virtual void RemoveTarget(plSceneObject* so);
//
// hsBool HandleControlInput(plControlEventMsg* pMsg);
// virtual hsBool IEval(double secs, hsScalar del, UInt32 dirty);
//
// void SetMoving(hsBool b);
// hsBool IsMoving() { return bMoving; }
//
// hsBool HasFlag(int f) const { return fFlags.IsBitSet(f); }
// void SetFlag(int f) { fFlags.SetBit(f); }
// void ClearFlag(int which) { fFlags.ClearBit( which ); }
//
// static void SetTurnRate(float f) {fTurnRate = f;}
// static void SetAcceleration(float f) {fAcceleration = f;}
// static void SetDeceleration(float f) {fDeceleration = f;}
// static void SetVelocity(float f) {fMaxVelocity = f;}
//
//
//};
//
//#endif plPlayerModifier_inc

View File

@ -0,0 +1,107 @@
/*==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 "plANDConditionalObject.h"
#include "../plPhysical/plDetectorModifier.h"
#include "hsResMgr.h"
#include "../../NucleusLib/pnModifier/plConditionalObject.h"
#include "../../NucleusLib/pnModifier/plLogicModBase.h"
#include "../plMessage/plCondRefMsg.h"
plANDConditionalObject::plANDConditionalObject()
{
}
plANDConditionalObject::~plANDConditionalObject()
{
for (int i = 0; i < fChildren.Count(); i++)
delete (fChildren[i]);
}
hsBool plANDConditionalObject::MsgReceive(plMessage* msg)
{
plCondRefMsg* pCondMsg = plCondRefMsg::ConvertNoRef(msg);
if (pCondMsg)
{
fChildren[pCondMsg->fWhich] = plConditionalObject::ConvertNoRef( pCondMsg->GetRef() );
return true;
}
return plConditionalObject::MsgReceive(msg);
}
void plANDConditionalObject::Evaluate()
{
if (!Satisfied())
{
for (int i = 0; i < fChildren.Count(); i++)
{
if (!fChildren[i]->Satisfied())
return;
}
SetSatisfied(true);
fLogicMod->RequestTrigger();
}
else
{
for (int i = 0; i < fChildren.Count(); i++)
{
if (fChildren[i]->Satisfied())
return;
}
SetSatisfied(false);
}
}
void plANDConditionalObject::Reset()
{
for (int i = 0; i < fChildren.Count(); i++)
fChildren[i]->Reset();
}
void plANDConditionalObject::Read(hsStream* stream, hsResMgr* mgr)
{
plConditionalObject::Read(stream, mgr);
plCondRefMsg* refMsg;
int n = stream->ReadSwap32();
fChildren.SetCountAndZero(n);
for(int i = 0; i < n; i++ )
{
refMsg = TRACKED_NEW plCondRefMsg(GetKey(), i);
mgr->ReadKeyNotifyMe(stream,refMsg, plRefFlags::kActiveRef);
}
}
void plANDConditionalObject::Write(hsStream* stream, hsResMgr* mgr)
{
plConditionalObject::Write(stream, mgr);
stream->WriteSwap32(fChildren.GetCount());
for( int i = 0; i < fChildren.GetCount(); i++ )
fChildren[i]->Write(stream, mgr);
}

View File

@ -0,0 +1,55 @@
/*==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 plANDConditionalObject_inc
#define plANDConditionalObject_inc
#include "../../NucleusLib/pnModifier/plConditionalObject.h"
#include "hsTemplates.h"
class plANDConditionalObject : public plConditionalObject
{
protected:
hsTArray<plConditionalObject*> fChildren;
public:
plANDConditionalObject();
~plANDConditionalObject();
CLASSNAME_REGISTER( plANDConditionalObject );
GETINTERFACE_ANY( plANDConditionalObject, plConditionalObject );
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
hsBool MsgReceive(plMessage* msg);
void Evaluate();
void Reset();
};
#endif // plANDConditionalObject_inc

View File

@ -0,0 +1,205 @@
/*==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 "plActivatorConditionalObject.h"
#include "../plPhysical/plDetectorModifier.h"
#include "../../NucleusLib/pnModifier/plLogicModBase.h"
#include "../plMessage/plActivatorMsg.h"
#include "../pnMessage/plNotifyMsg.h"
plActivatorConditionalObject::plActivatorConditionalObject()
{
SetFlag(kLocalElement); // since it relies on user input
}
hsBool plActivatorConditionalObject::MsgReceive(plMessage* msg)
{
plActivatorMsg* pDetectorMsg = plActivatorMsg::ConvertNoRef(msg);
if (pDetectorMsg)
{
if (pDetectorMsg->fTriggerType == plActivatorMsg::kVolumeEnter || pDetectorMsg->fTriggerType == plActivatorMsg::kVolumeExit)
return plConditionalObject::MsgReceive(msg);
for (int i = 0; i < fActivators.Count(); i++)
{
if (pDetectorMsg && pDetectorMsg->GetSender() == fActivators[i])
{
if (pDetectorMsg->fTriggerType == plActivatorMsg::kUnPickedTrigger ||
pDetectorMsg->fTriggerType == plActivatorMsg::kExitUnTrigger ||
pDetectorMsg->fTriggerType == plActivatorMsg::kEnterUnTrigger ||
pDetectorMsg->fTriggerType == plActivatorMsg::kCollideUnTrigger )
{
// is this a toggle activator?
if (IsToggle())
return true;
// are we in a triggered state?
if (fLogicMod->HasFlag(plLogicModBase::kTriggered))
{
if (pDetectorMsg->fTriggerType == plActivatorMsg::kUnPickedTrigger)
fLogicMod->GetNotify()->AddPickEvent(pDetectorMsg->fHitterObj, pDetectorMsg->fPickedObj, false, pDetectorMsg->fHitPoint);
if ((pDetectorMsg->fTriggerType == plActivatorMsg::kCollideExit) ||
(pDetectorMsg->fTriggerType == plActivatorMsg::kVolumeExit) )
fLogicMod->GetNotify()->AddCollisionEvent(true, pDetectorMsg->fHitterObj, pDetectorMsg->fHiteeObj);
if ((pDetectorMsg->fTriggerType == plActivatorMsg::kCollideEnter) ||
(pDetectorMsg->fTriggerType == plActivatorMsg::kVolumeEnter) )
fLogicMod->GetNotify()->AddCollisionEvent(false, pDetectorMsg->fHitterObj, pDetectorMsg->fHiteeObj);
fLogicMod->RequestUnTrigger();
}
}
else
{
// are we a toggle that has been triggered?
// are we in a triggered state?
if (fLogicMod->HasFlag(plLogicModBase::kTriggered) && IsToggle())
{
if (pDetectorMsg->fTriggerType == plActivatorMsg::kUnPickedTrigger)
fLogicMod->GetNotify()->AddPickEvent(pDetectorMsg->fHitterObj, pDetectorMsg->fPickedObj, false, pDetectorMsg->fHitPoint);
if ((pDetectorMsg->fTriggerType == plActivatorMsg::kCollideExit) ||
(pDetectorMsg->fTriggerType == plActivatorMsg::kVolumeExit) )
fLogicMod->GetNotify()->AddCollisionEvent(true, pDetectorMsg->fHitterObj, pDetectorMsg->fHiteeObj);
if ((pDetectorMsg->fTriggerType == plActivatorMsg::kCollideEnter) ||
(pDetectorMsg->fTriggerType == plActivatorMsg::kVolumeEnter) )
fLogicMod->GetNotify()->AddCollisionEvent(false, pDetectorMsg->fHitterObj, pDetectorMsg->fHiteeObj);
fLogicMod->RequestUnTrigger();
return true;
}
if (!fLogicMod->VerifyConditions( pDetectorMsg ))
return false;
// this is used as part of a picked detector sometimes...
if (pDetectorMsg->fTriggerType == plActivatorMsg::kPickedTrigger)
fLogicMod->GetNotify()->AddPickEvent(pDetectorMsg->fHitterObj, pDetectorMsg->fPickedObj, true, pDetectorMsg->fHitPoint);
if ((pDetectorMsg->fTriggerType == plActivatorMsg::kCollideExit) ||
(pDetectorMsg->fTriggerType == plActivatorMsg::kVolumeExit) )
{
fLogicMod->GetNotify()->AddCollisionEvent(false, pDetectorMsg->fHitterObj, pDetectorMsg->fHiteeObj);
}
if ((pDetectorMsg->fTriggerType == plActivatorMsg::kCollideEnter) ||
(pDetectorMsg->fTriggerType == plActivatorMsg::kVolumeEnter) )
{
fLogicMod->GetNotify()->AddCollisionEvent(true, pDetectorMsg->fHitterObj, pDetectorMsg->fHiteeObj);
}
SetSatisfied(true);
//hsBool netRequest = msg->HasBCastFlag(plMessage::kNetNonLocal);
//fLogicMod->RequestTrigger(netRequest);
fLogicMod->RequestTrigger(false);
}
return true;
}
}
}
return plConditionalObject::MsgReceive(msg);
}
void plActivatorConditionalObject::Read(hsStream* stream, hsResMgr* mgr)
{
plConditionalObject::Read(stream, mgr);
fActivators.Reset();
int n = stream->ReadSwap32();
for (int i = 0; i < n; i++)
fActivators.Append(mgr->ReadKey(stream));
}
void plActivatorConditionalObject::Write(hsStream* stream, hsResMgr* mgr)
{
plConditionalObject::Write(stream, mgr);
stream->WriteSwap32(fActivators.Count());
for (int i = 0; i < fActivators.Count(); i++)
mgr->WriteKey(stream, fActivators[i]);
}
void plActivatorConditionalObject::SetActivatorKey(plKey k)
{
fActivators.Append(k);
}
//
// plActivatorActivatorConditional
//
hsBool plActivatorActivatorConditionalObject::MsgReceive(plMessage* msg)
{
plNotifyMsg* pDetectorMsg = plNotifyMsg::ConvertNoRef(msg);
if (pDetectorMsg)
{
if (!pDetectorMsg->fState && fLogicMod->HasFlag(plLogicModBase::kTriggered))
{
fLogicMod->RequestUnTrigger();
}
else
if (pDetectorMsg->fState && !fLogicMod->HasFlag(plLogicModBase::kTriggered))
{
if (!fLogicMod->VerifyConditions( pDetectorMsg ))
return false;
SetSatisfied(true);
fLogicMod->RequestTrigger(false);
}
return true;
}
return plConditionalObject::MsgReceive(msg);
}
hsBool plVolActivatorConditionalObject::MsgReceive(plMessage* msg)
{
plActivatorMsg* pDetectorMsg = plActivatorMsg::ConvertNoRef(msg);
if (pDetectorMsg)
{
for (int i = 0; i < fActivators.Count(); i++)
{
if (!fLogicMod->VerifyConditions( pDetectorMsg ))
return false;
if ((pDetectorMsg->fTriggerType == plActivatorMsg::kCollideExit) ||
(pDetectorMsg->fTriggerType == plActivatorMsg::kVolumeExit) )
{
fLogicMod->GetNotify()->AddCollisionEvent(false, pDetectorMsg->fHitterObj, pDetectorMsg->fHiteeObj);
}
if ((pDetectorMsg->fTriggerType == plActivatorMsg::kCollideEnter) ||
(pDetectorMsg->fTriggerType == plActivatorMsg::kVolumeEnter) )
{
fLogicMod->GetNotify()->AddCollisionEvent(true, pDetectorMsg->fHitterObj, pDetectorMsg->fHiteeObj);
}
SetSatisfied(true);
fLogicMod->RequestTrigger(false);
}
return true;
}
return plConditionalObject::MsgReceive(msg);
}

View File

@ -0,0 +1,90 @@
/*==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 plActivatorConditionalObject_inc
#define plActivatorConditionalObject_inc
#include "../../NucleusLib/pnModifier/plConditionalObject.h"
#include "hsTemplates.h"
class plKey;
class plActivatorConditionalObject : public plConditionalObject
{
protected:
hsTArray<plKey> fActivators;
public:
plActivatorConditionalObject();
~plActivatorConditionalObject(){;}
CLASSNAME_REGISTER( plActivatorConditionalObject );
GETINTERFACE_ANY( plActivatorConditionalObject, plConditionalObject );
virtual hsBool MsgReceive(plMessage* msg);
void Evaluate(){;}
void SetActivatorKey(plKey k);
void Reset() { SetSatisfied(false); }
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
};
class plActivatorActivatorConditionalObject : public plActivatorConditionalObject
{
public:
plActivatorActivatorConditionalObject(){;}
~plActivatorActivatorConditionalObject(){;}
CLASSNAME_REGISTER( plActivatorActivatorConditionalObject );
GETINTERFACE_ANY( plActivatorActivatorConditionalObject, plActivatorConditionalObject );
virtual hsBool MsgReceive(plMessage* msg);
};
class plVolActivatorConditionalObject : public plActivatorConditionalObject
{
public:
plVolActivatorConditionalObject(){;}
~plVolActivatorConditionalObject(){;}
CLASSNAME_REGISTER( plVolActivatorConditionalObject );
GETINTERFACE_ANY( plVolActivatorConditionalObject, plActivatorConditionalObject );
virtual hsBool MsgReceive(plMessage* msg);
};
#endif // plActivatorConditionalObject_inc

View File

@ -0,0 +1,82 @@
/*==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 "plAnimationEventConditionalObject.h"
#include "../pnInputCore/plKeyDef.h"
#include "../plModifier/plSimpleModifier.h"
#include "../../NucleusLib/pnModifier/plLogicModBase.h"
#include "plgDispatch.h"
#include "hsResMgr.h"
#include "../plMessage/plAnimCmdMsg.h"
plAnimationEventConditionalObject::plAnimationEventConditionalObject(plKey pTargetModifier) :
fTarget(pTargetModifier),
fAction(kEventEnd)
{
}
hsBool plAnimationEventConditionalObject::MsgReceive(plMessage* msg)
{
plEventCallbackMsg* pMsg = plEventCallbackMsg::ConvertNoRef(msg);
if (pMsg)
{
SetSatisfied(true);
// fLogicMod->RequestTrigger();
return true;
}
return plConditionalObject::MsgReceive(msg);
}
void plAnimationEventConditionalObject::SetEvent(const CallbackEvent b, hsScalar time)
{
plAnimCmdMsg* pMsg = TRACKED_NEW plAnimCmdMsg;
pMsg->AddReceiver(fTarget);
pMsg->SetSender( GetKey() );
plEventCallbackMsg* cb = TRACKED_NEW plEventCallbackMsg(GetKey(), b, 0, time);
pMsg->AddCallback( cb );
hsRefCnt_SafeUnRef(cb);
pMsg->SetCmd( plAnimCmdMsg::kAddCallbacks );
plgDispatch::MsgSend( pMsg );
}
void plAnimationEventConditionalObject::Read(hsStream* stream, hsResMgr* mgr)
{
plConditionalObject::Read(stream, mgr);
fTarget = mgr->ReadKey(stream);
fAction = (CallbackEvent)stream->ReadSwap32();
}
void plAnimationEventConditionalObject::Write(hsStream* stream, hsResMgr* mgr)
{
plConditionalObject::Write(stream, mgr);
mgr->WriteKey(stream, fTarget);
stream->WriteSwap32(fAction);
}

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 plAnimationEventConditionalObject_inc
#define plAnimationEventConditionalObject_inc
#include "../pnModifier/plConditionalObject.h"
#include "../pnInputCore/plKeyDef.h"
#include "../pnMessage/plEventCallbackMsg.h" // AnimationEvent's defined here
class plAnimationEventConditionalObject : public plConditionalObject
{
protected:
CallbackEvent fAction;
plKey fTarget;
public:
plAnimationEventConditionalObject(){;}
plAnimationEventConditionalObject(plKey pTargetModifier);
~plAnimationEventConditionalObject(){;}
CLASSNAME_REGISTER( plAnimationEventConditionalObject );
GETINTERFACE_ANY( plAnimationEventConditionalObject, plConditionalObject );
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
hsBool MsgReceive(plMessage* msg);
void Evaluate(){;}
void Reset() { SetSatisfied(false); }
void SetEvent(const CallbackEvent b, hsScalar time = 0.0f);
};
#endif // plAnimationEventConditionalObject_inc

View File

@ -0,0 +1,84 @@
/*==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 plConditionalObjectCreatable_inc
#define plConditionalObjectCreatable_inc
#include "../pnFactory/plCreator.h"
#include "plANDConditionalObject.h"
REGISTER_CREATABLE( plANDConditionalObject );
#include "plORConditionalObject.h"
REGISTER_CREATABLE( plORConditionalObject );
#include "plPickedConditionalObject.h"
REGISTER_CREATABLE( plPickedConditionalObject );
#include "plActivatorConditionalObject.h"
REGISTER_CREATABLE( plActivatorConditionalObject );
REGISTER_CREATABLE( plActivatorActivatorConditionalObject );
REGISTER_CREATABLE( plVolActivatorConditionalObject );
#include "plKeyPressConditionalObject.h"
REGISTER_CREATABLE( plKeyPressConditionalObject );
#include "plAnimationEventConditionalObject.h"
REGISTER_CREATABLE( plAnimationEventConditionalObject );
#include "plControlEventConditionalObject.h"
REGISTER_CREATABLE( plControlEventConditionalObject );
#include "plObjectInBoxConditionalObject.h"
REGISTER_CREATABLE( plObjectInBoxConditionalObject );
REGISTER_CREATABLE( plVolumeSensorConditionalObject );
REGISTER_CREATABLE( plVolumeSensorConditionalObjectNoArbitration );
#include "plLocalPlayerInBoxConditionalObject.h"
REGISTER_CREATABLE( plLocalPlayerInBoxConditionalObject );
#include "plObjectIntersectPlaneConditionalObject.h"
REGISTER_CREATABLE( plObjectIntersectPlaneConditionalObject );
#include "plLocalPlayerIntersectPlaneConditionalObject.h"
REGISTER_CREATABLE( plLocalPlayerIntersectPlaneConditionalObject );
#include "plFacingConditionalObject.h"
REGISTER_CREATABLE( plFacingConditionalObject );
#endif // plConditionalObjectCreatable_inc

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==*/
#include "hsTypes.h"
#include "plControlEventConditionalObject.h"
#include "../plPhysical/plDetectorModifier.h"
#include "../../NucleusLib/pnModifier/plLogicModBase.h"
#include "../plMessage/plInputEventMsg.h"
plControlEventConditionalObject::plControlEventConditionalObject()
{
}
hsBool plControlEventConditionalObject::MsgReceive(plMessage* msg)
{
plControlEventMsg* pControlMsg = plControlEventMsg::ConvertNoRef(msg);
if( pControlMsg )
{
if (pControlMsg->GetControlCode() == fControlEvent && pControlMsg->ControlActivated() && !Satisfied() )
{
SetSatisfied(true);
// fLogicMod->RequestTrigger();
}
else
if (pControlMsg->GetControlCode() == fControlEvent && !pControlMsg->ControlActivated() && Satisfied() )
{
SetSatisfied(false);
}
return true;
}
return plConditionalObject::MsgReceive(msg);
}
void plControlEventConditionalObject::Read(hsStream* stream, hsResMgr* mgr)
{
plConditionalObject::Read(stream, mgr);
fControlEvent = (ControlEventCode)stream->ReadSwap32();
}
void plControlEventConditionalObject::Write(hsStream* stream, hsResMgr* mgr)
{
plConditionalObject::Write(stream, mgr);
stream->WriteSwap32((UInt32)fControlEvent);
}

View File

@ -0,0 +1,60 @@
/*==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 plControlEventConditionalObject_inc
#define plControlEventConditionalObject_inc
#include "../../NucleusLib/pnModifier/plConditionalObject.h"
#include "../../NucleusLib/pnInputCore/plControlEventCodes.h"
class plControlEventConditionalObject : public plConditionalObject
{
protected:
public:
plControlEventConditionalObject();
~plControlEventConditionalObject(){;}
CLASSNAME_REGISTER( plControlEventConditionalObject );
GETINTERFACE_ANY( plControlEventConditionalObject, plConditionalObject );
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
hsBool MsgReceive(plMessage* msg);
void Evaluate(){;}
void Reset() { SetSatisfied(false); }
ControlEventCode fControlEvent;
};
#endif // plControlEventConditionalObject_inc

View File

@ -0,0 +1,133 @@
/*==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 "plFacingConditionalObject.h"
#include "plgDispatch.h"
#include "../../NucleusLib/pnModifier/plLogicModBase.h"
#include "../plMessage/plActivatorMsg.h"
#include "../pnSceneObject/plSceneObject.h"
#include "../pnSceneObject/plCoordinateInterface.h"
#include "../pnKeyedObject/plKey.h"
#include "../pnMessage/plNotifyMsg.h"
#include "../pnMessage/plFakeOutMsg.h"
#include "../pnNetCommon/plNetApp.h"
plFacingConditionalObject::plFacingConditionalObject() :
fTolerance(-1.0f),
fDirectional(false)
{
SetSatisfied(true);
}
hsBool plFacingConditionalObject::MsgReceive(plMessage* msg)
{
return plConditionalObject::MsgReceive(msg);
}
void plFacingConditionalObject::Write(hsStream* stream, hsResMgr* mgr)
{
plConditionalObject::Write(stream, mgr);
stream->WriteSwap(fTolerance);
stream->WriteBool(fDirectional);
}
void plFacingConditionalObject::Read(hsStream* stream, hsResMgr* mgr)
{
plConditionalObject::Read(stream, mgr);
stream->ReadSwap(&fTolerance);
fDirectional = stream->ReadBool();
}
hsBool plFacingConditionalObject::Verify(plMessage* msg)
{
plActivatorMsg* pActivateMsg = plActivatorMsg::ConvertNoRef(msg);
if (pActivateMsg && pActivateMsg->fHitterObj)
{
plSceneObject* pPlayer = plSceneObject::ConvertNoRef(pActivateMsg->fHitterObj->ObjectIsLoaded());
if (pPlayer)
{
hsVector3 playerView = pPlayer->GetCoordinateInterface()->GetLocalToWorld().GetAxis(hsMatrix44::kView);
hsVector3 ourView;
if (fDirectional)
ourView = fLogicMod->GetTarget()->GetCoordinateInterface()->GetLocalToWorld().GetAxis(hsMatrix44::kView);
else
{
hsVector3 v(fLogicMod->GetTarget()->GetCoordinateInterface()->GetLocalToWorld().GetTranslate() - pPlayer->GetCoordinateInterface()->GetLocalToWorld().GetTranslate());
ourView = v;
ourView.Normalize();
}
hsScalar dot = playerView * ourView;
if (dot >= fTolerance)
{
fLogicMod->GetNotify()->AddFacingEvent( pActivateMsg->fHitterObj, fLogicMod->GetTarget()->GetKey(), dot, true);
return true;
}
else
{
return false;
}
}
}
plFakeOutMsg* pFakeMsg = plFakeOutMsg::ConvertNoRef(msg);
if (pFakeMsg && plNetClientApp::GetInstance()->GetLocalPlayerKey())
{
// sanity check
if (!fLogicMod->GetTarget()->GetCoordinateInterface())
return false;
plSceneObject* pPlayer = plSceneObject::ConvertNoRef(plNetClientApp::GetInstance()->GetLocalPlayerKey()->ObjectIsLoaded());
if (pPlayer)
{
hsVector3 playerView = pPlayer->GetCoordinateInterface()->GetLocalToWorld().GetAxis(hsMatrix44::kView);
hsVector3 ourView;
if (fDirectional)
ourView = fLogicMod->GetTarget()->GetCoordinateInterface()->GetLocalToWorld().GetAxis(hsMatrix44::kView);
else
{
hsVector3 v(fLogicMod->GetTarget()->GetCoordinateInterface()->GetLocalToWorld().GetTranslate() - pPlayer->GetCoordinateInterface()->GetLocalToWorld().GetTranslate());
ourView = v;
ourView.fZ = playerView.fZ;
ourView.Normalize();
}
hsScalar dot = playerView * ourView;
if (dot >= fTolerance)
{
return true;
}
else
{
if (!IsToggle())
{
fLogicMod->GetNotify()->AddFacingEvent( pPlayer->GetKey(), fLogicMod->GetTarget()->GetKey(), dot, false);
fLogicMod->RequestUnTrigger();
return false;
}
}
}
}
return false;
}

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 plFacingConditionalObject_inc
#define plFacingConditionalObject_inc
#include "../../NucleusLib/pnModifier/plConditionalObject.h"
class plSceneObject;
class plFacingConditionalObject : public plConditionalObject
{
protected:
hsScalar fTolerance;
hsBool fDirectional;
public:
plFacingConditionalObject();
~plFacingConditionalObject(){;}
CLASSNAME_REGISTER( plFacingConditionalObject );
GETINTERFACE_ANY( plFacingConditionalObject, plConditionalObject );
hsBool MsgReceive(plMessage* msg);
void SetTolerance(hsScalar d) { fTolerance = d; }
void SetDirectional(hsBool d) { fDirectional = d; }
virtual hsBool Verify(plMessage* msg);
void Evaluate(){;}
void Reset() { SetSatisfied(true); }
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
};
#endif // plFacingConditionalObject_inc

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==*/
#include "hsTypes.h"
#include "plKeyPressConditionalObject.h"
#include "../plPhysical/plDetectorModifier.h"
#include "../../NucleusLib/pnModifier/plLogicModBase.h"
#include "../plMessage/plInputEventMsg.h"
plKeyPressConditionalObject::plKeyPressConditionalObject()
{
SetFlag(kLocalElement); // since it relies on user input
}
hsBool plKeyPressConditionalObject::MsgReceive(plMessage* msg)
{
plKeyEventMsg* pKeyMsg = plKeyEventMsg::ConvertNoRef(msg);
if( pKeyMsg )
{
if (pKeyMsg && pKeyMsg->GetKeyCode() == fKeyEvent && pKeyMsg->GetKeyDown() && !Satisfied() )
{
SetSatisfied(true);
// fLogicMod->RequestTrigger();
}
else
if (pKeyMsg && pKeyMsg->GetKeyCode() == fKeyEvent && !pKeyMsg->GetKeyDown() && Satisfied() )
{
SetSatisfied(false);
}
return true;
}
return plConditionalObject::MsgReceive(msg);
}
void plKeyPressConditionalObject::Read(hsStream* stream, hsResMgr* mgr)
{
plConditionalObject::Read(stream, mgr);
fKeyEvent = (plKeyDef)stream->ReadSwap32();
}
void plKeyPressConditionalObject::Write(hsStream* stream, hsResMgr* mgr)
{
plConditionalObject::Write(stream, mgr);
stream->WriteSwap32((UInt32)fKeyEvent);
}

View File

@ -0,0 +1,59 @@
/*==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 plKeyPressConditionalObject_inc
#define plKeyPressConditionalObject_inc
#include "../../NucleusLib/pnModifier/plConditionalObject.h"
#include "../../NucleusLib/pnInputCore/plKeyDef.h"
class plKeyPressConditionalObject : public plConditionalObject
{
protected:
plKeyDef fKeyEvent;
public:
plKeyPressConditionalObject();
~plKeyPressConditionalObject(){;}
CLASSNAME_REGISTER( plKeyPressConditionalObject );
GETINTERFACE_ANY( plKeyPressConditionalObject, plConditionalObject );
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
hsBool MsgReceive(plMessage* msg);
void Evaluate(){;}
void Reset() { SetSatisfied(false); }
void SetKeyEvent(const plKeyDef k ) { fKeyEvent = k; }
};
#endif // plKeyPressConditionalObject_inc

View File

@ -0,0 +1,53 @@
/*==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 "plLocalPlayerInBoxConditionalObject.h"
#include "../../PubUtilLib/plPhysical/plDetectorModifier.h"
#include "../../NucleusLib/pnModifier/plLogicModBase.h"
plLocalPlayerInBoxConditionalObject::plLocalPlayerInBoxConditionalObject()
{
// find the player's key here...
SetFlag(kLocalElement); // since it relies on the local player
}
hsBool plLocalPlayerInBoxConditionalObject::MsgReceive(plMessage* msg)
{
/*
if our target is within the bounds of the object our logic modifier is attached to...
{
SetSatisfied(true);
fLogicMod->RequestTrigger();
return true;
}
*/
return plConditionalObject::MsgReceive(msg);
}

View File

@ -0,0 +1,57 @@
/*==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 plLocalPlayerInBoxConditionalObject_inc
#define plLocalPlayerInBoxConditionalObject_inc
#include "../../NucleusLib/pnModifier/plConditionalObject.h"
class plKey;
class plLocalPlayerInBoxConditionalObject : public plConditionalObject
{
protected:
plKey fPlayer;
plKey fBox;
public:
plLocalPlayerInBoxConditionalObject();
~plLocalPlayerInBoxConditionalObject(){;}
CLASSNAME_REGISTER( plLocalPlayerInBoxConditionalObject );
GETINTERFACE_ANY( plLocalPlayerInBoxConditionalObject, plConditionalObject );
hsBool MsgReceive(plMessage* msg);
void SetBox(plKey pKey) { fBox = pKey; }
void Evaluate(){;}
void Reset() { SetSatisfied(false); }
};
#endif // plLocalPlayerInBoxConditionalObject_inc

View File

@ -0,0 +1,52 @@
/*==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 "plLocalPlayerIntersectPlaneConditionalObject.h"
#include "../../PubUtilLib/plPhysical/plDetectorModifier.h"
#include "../../NucleusLib/pnModifier/plLogicModBase.h"
plLocalPlayerIntersectPlaneConditionalObject::plLocalPlayerIntersectPlaneConditionalObject()
{
SetFlag(kLocalElement); // since it relies on the local player
}
hsBool plLocalPlayerIntersectPlaneConditionalObject::MsgReceive(plMessage* msg)
{
/*
if our target is within the bounds of the object our logic modifier is attached to...
{
SetSatisfied(true);
fLogicMod->RequestTrigger();
return true;
}
*/
return plConditionalObject::MsgReceive(msg);
}

View File

@ -0,0 +1,58 @@
/*==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 plLocalPlayerIntersectPlaneConditionalObject_inc
#define plLocalPlayerIntersectPlaneConditionalObject_inc
#include "../../NucleusLib/pnModifier/plConditionalObject.h"
class plKey;
class plLocalPlayerIntersectPlaneConditionalObject : public plConditionalObject
{
protected:
plKey fTarget;
plKey fPlane;
public:
plLocalPlayerIntersectPlaneConditionalObject();
~plLocalPlayerIntersectPlaneConditionalObject(){;}
CLASSNAME_REGISTER( plLocalPlayerIntersectPlaneConditionalObject );
GETINTERFACE_ANY( plLocalPlayerIntersectPlaneConditionalObject, plConditionalObject );
hsBool MsgReceive(plMessage* msg);
void SetTarget(plKey pKey) { fTarget = pKey; }
void SetPlane(plKey pKey) { fPlane = pKey; }
void Evaluate(){;}
void Reset() { SetSatisfied(false); }
};
#endif // plLocalPlayerIntersectPlaneConditionalObject_inc

View File

@ -0,0 +1,112 @@
/*==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 "plORConditionalObject.h"
#include "../plPhysical/plDetectorModifier.h"
#include "hsResMgr.h"
#include "../../NucleusLib/pnModifier/plLogicModBase.h"
#include "../plMessage/plCondRefMsg.h"
plORConditionalObject::plORConditionalObject()
{
}
plORConditionalObject::~plORConditionalObject()
{
fChildren.SetCountAndZero(0);
}
hsBool plORConditionalObject::MsgReceive(plMessage* msg)
{
plCondRefMsg* pCondMsg = plCondRefMsg::ConvertNoRef(msg);
if (pCondMsg)
{
fChildren[pCondMsg->fWhich] = plConditionalObject::ConvertNoRef( pCondMsg->GetRef() );
fChildren[pCondMsg->fWhich]->SetLogicMod(fLogicMod);
return true;
}
return plConditionalObject::MsgReceive(msg);
}
void plORConditionalObject::SetLogicMod(plLogicModBase* pMod)
{
fLogicMod = pMod;
for (int i = 0; i < fChildren.Count(); i++)
{
if( fChildren[i] )
fChildren[i]->SetLogicMod(pMod);
}
}
hsBool plORConditionalObject::Satisfied()
{
for (int i = 0; i < fChildren.Count(); i++)
{
if (fChildren[i]->Satisfied())
return true;
}
return false;
}
void plORConditionalObject::AddChild(plConditionalObject* pObj)
{
fChildren.Append(pObj);
pObj->SetLogicMod(fLogicMod);
}
void plORConditionalObject::Reset()
{
for (int i = 0; i < fChildren.Count(); i++)
fChildren[i]->Reset();
}
void plORConditionalObject::Read(hsStream* stream, hsResMgr* mgr)
{
plConditionalObject::Read(stream, mgr);
plCondRefMsg* refMsg;
int n = stream->ReadSwap32();
fChildren.SetCountAndZero(n);
for(int i = 0; i < n; i++ )
{
refMsg = TRACKED_NEW plCondRefMsg(GetKey(), i);
mgr->ReadKeyNotifyMe(stream,refMsg, plRefFlags::kActiveRef);
}
}
void plORConditionalObject::Write(hsStream* stream, hsResMgr* mgr)
{
plConditionalObject::Write(stream, mgr);
stream->WriteSwap32(fChildren.GetCount());
for( int i = 0; i < fChildren.GetCount(); i++ )
mgr->WriteKey(stream, fChildren[i]);
}

View File

@ -0,0 +1,60 @@
/*==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 plORConditionalObject_inc
#define plORConditionalObject_inc
#include "../../NucleusLib/pnModifier/plConditionalObject.h"
#include "hsTemplates.h"
class plORConditionalObject : public plConditionalObject
{
protected:
hsTArray<plConditionalObject*> fChildren;
public:
plORConditionalObject();
~plORConditionalObject();
CLASSNAME_REGISTER( plORConditionalObject );
GETINTERFACE_ANY( plORConditionalObject, plConditionalObject );
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
virtual hsBool Satisfied();
virtual hsBool MsgReceive(plMessage* msg);
void Evaluate(){;}
void Reset();
virtual void SetLogicMod(plLogicModBase* pMod);
void AddChild(plConditionalObject* pObj);
};
#endif // plORConditionalObject_inc

View File

@ -0,0 +1,432 @@
/*==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 "plObjectInBoxConditionalObject.h"
#include "../../PubUtilLib/plPhysical/plDetectorModifier.h"
#include "../../NucleusLib/pnModifier/plLogicModBase.h"
#include "../../PubUtilLib/plMessage/plActivatorMsg.h"
#include "../pnMessage/plNotifyMsg.h"
#include "../pnMessage/plFakeOutMsg.h"
#include "../pnNetCommon/plNetApp.h"
#include "../plAvatar/plArmatureMod.h"
#include "../pnSceneObject/plSceneObject.h"
bool plVolumeSensorConditionalObject::makeBriceHappyVar = true;
plObjectInBoxConditionalObject::plObjectInBoxConditionalObject() :
fCurrentTrigger(nil)
{
SetSatisfied(true);
}
hsBool plObjectInBoxConditionalObject::MsgReceive(plMessage* msg)
{
plActivatorMsg* pActivateMsg = plActivatorMsg::ConvertNoRef(msg);
if (pActivateMsg)
{
if (pActivateMsg->fTriggerType == plActivatorMsg::kVolumeEnter)
{
fInside.Append(pActivateMsg->fHitterObj);
return true;
}
else
if (pActivateMsg->fTriggerType == plActivatorMsg::kVolumeExit)
{
for (int i = 0; i < fInside.Count(); i++)
{
if (fInside[i] == pActivateMsg->fHitterObj)
{
fInside.Remove(i);
if (pActivateMsg->fHitterObj == fCurrentTrigger && fCurrentTrigger && fLogicMod->HasFlag(plLogicModBase::kTriggered) && !IsToggle())
{
fCurrentTrigger = nil;
fLogicMod->GetNotify()->AddContainerEvent( pActivateMsg->fHiteeObj, pActivateMsg->fHitterObj, false );
fLogicMod->RequestUnTrigger();
}
}
}
return true;
}
return false;
}
return plConditionalObject::MsgReceive(msg);
}
hsBool plObjectInBoxConditionalObject::Verify(plMessage* msg)
{
plActivatorMsg* pActivateMsg = plActivatorMsg::ConvertNoRef(msg);
if (pActivateMsg)
{
for (int i = 0; i < fInside.Count(); i++)
{
if (pActivateMsg->fHitterObj == fInside[i])
{
fLogicMod->GetNotify()->AddContainerEvent( pActivateMsg->fHiteeObj, pActivateMsg->fHitterObj, true );
fCurrentTrigger = pActivateMsg->fHiteeObj;
return true;
}
}
}
plFakeOutMsg* pFakeMsg = plFakeOutMsg::ConvertNoRef(msg);
if (pFakeMsg && plNetClientApp::GetInstance()->GetLocalPlayerKey())
{
for (int i = 0; i < fInside.Count(); i++)
{
if (plNetClientApp::GetInstance()->GetLocalPlayerKey() == fInside[i])
return true;
}
}
return false;
}
//
// volume sensor conditional
//
plVolumeSensorConditionalObject::plVolumeSensorConditionalObject() :
fTrigNum(-1),
fType(0),
fFirst(false),
fTriggered(false),
fIgnoreExtraEnters(true)
{
SetSatisfied(true);
}
hsBool plVolumeSensorConditionalObject::MsgReceive(plMessage* msg)
{
plActivatorMsg* pActivateMsg = plActivatorMsg::ConvertNoRef(msg);
if (pActivateMsg)
{
// single player hack
if (!fLogicMod->HasFlag(plLogicModBase::kRequestingTrigger))
fLogicMod->GetNotify()->ClearEvents();
if (pActivateMsg->fTriggerType == plActivatorMsg::kVolumeEnter)
{
int i;
for (i = 0; i < fInside.Count(); i++)
{
if (fInside[i] == pActivateMsg->fHitterObj)
{
if (fIgnoreExtraEnters)
return false; // this is the "correct" way to handle this situation
break; // this is for those special situations where, due to some physics oddity, we need to allow the avatar to enter without exiting
}
}
if (i == fInside.Count())
fInside.Append(pActivateMsg->fHitterObj);
if (makeBriceHappyVar)
{
plSceneObject *pObj = plSceneObject::ConvertNoRef( pActivateMsg->fHitterObj->ObjectIsLoaded() );
if( pObj )
{
//need to check for human vs quabish type things in here
int i;
for( i = 0; i < pObj->GetNumModifiers(); i++ )
{
if (plArmatureMod::ConvertNoRef( pObj->GetModifier(i)))
{
if (plNetClientApp::GetInstance()->GetLocalPlayerKey() != pActivateMsg->fHitterObj)
{
plArmatureMod *am=const_cast<plArmatureMod*>( plArmatureMod::ConvertNoRef(pObj->GetModifier(i)));
if((am->IsLocalAI())==nil)
{
return false;
}
}
}
}
plSynchedObject* syncObj = (plSynchedObject*)pObj;
if (syncObj->IsLocallyOwned() != plSynchedObject::kYes)
{
return false;
}
}
}
if (fType == kTypeEnter)
{
fLogicMod->GetNotify()->AddCollisionEvent(true, pActivateMsg->fHitterObj, pActivateMsg->fHiteeObj, false);
fLogicMod->RequestTrigger(false);
}
else
{
fLogicMod->GetNotify()->AddCollisionEvent(false, pActivateMsg->fHitterObj, pActivateMsg->fHiteeObj, false);
fLogicMod->RequestUnTrigger();
}
return false;
}
else
if (pActivateMsg->fTriggerType == plActivatorMsg::kVolumeExit)
{
for (int i = 0; i < fInside.Count(); i++)
{
if (fInside[i] == pActivateMsg->fHitterObj)
{
fInside.Remove(i);
if (makeBriceHappyVar)
{
//need to check for human vs quabish type things in here
plSceneObject *pObj = plSceneObject::ConvertNoRef( pActivateMsg->fHitterObj->ObjectIsLoaded() );
if( pObj )
{
int i;
for( i = 0; i < pObj->GetNumModifiers(); i++ )
{
if (plArmatureMod::ConvertNoRef( pObj->GetModifier(i)))
{
if (plNetClientApp::GetInstance()->GetLocalPlayerKey() != pActivateMsg->fHitterObj)
{
plArmatureMod *am=const_cast<plArmatureMod*>( plArmatureMod::ConvertNoRef(pObj->GetModifier(i)));
if((am->IsLocalAI())==nil)
{
return false;
}
}
}
}
plSynchedObject* syncObj = (plSynchedObject*)pObj;
if (syncObj->IsLocallyOwned() != plSynchedObject::kYes)
{
return false;
}
}
}
if (fType == kTypeExit)
{
fLogicMod->GetNotify()->AddCollisionEvent(false, pActivateMsg->fHitterObj, pActivateMsg->fHiteeObj, false);
fLogicMod->RequestTrigger(false);
}
else
{
fLogicMod->GetNotify()->AddCollisionEvent(true, pActivateMsg->fHitterObj, pActivateMsg->fHiteeObj, false);
fLogicMod->RequestUnTrigger();
}
return false;
}
}
}
return false;
}
return plConditionalObject::MsgReceive(msg);
}
hsBool plVolumeSensorConditionalObject::Satisfied()
{
if (fType == kTypeExit && fFirst && !fTriggered)
{
if (fInside.Count())
fTriggered = true;
return true;
}
if (fTriggered)
{
if (fInside.Count() == 0)
fTriggered = false;
return false;
}
if (fTrigNum == -1)
return true;
if (fInside.Count() == fTrigNum)
return true;
else
return false;
}
void plVolumeSensorConditionalObject::Read(hsStream* stream, hsResMgr* mgr)
{
plConditionalObject::Read(stream, mgr);
fTrigNum = stream->ReadSwap32();
fType = stream->ReadSwap32();
fFirst = stream->ReadBool();
}
void plVolumeSensorConditionalObject::Write(hsStream* stream, hsResMgr* mgr)
{
plConditionalObject::Write(stream, mgr);
stream->WriteSwap32(fTrigNum);
stream->WriteSwap32(fType);
stream->WriteBool(fFirst);
}
#include "../pnMessage/plPlayerPageMsg.h"
#include "../../NucleusLib/inc/plgDispatch.h"
hsBool plVolumeSensorConditionalObjectNoArbitration::MsgReceive(plMessage* msg)
{
plActivatorMsg* pActivateMsg = plActivatorMsg::ConvertNoRef(msg);
if (pActivateMsg)
{
// single player hack
if (!fLogicMod->HasFlag(plLogicModBase::kRequestingTrigger))
fLogicMod->GetNotify()->ClearEvents();
fHittee= pActivateMsg->fHiteeObj;
if (pActivateMsg->fTriggerType == plActivatorMsg::kVolumeEnter)
{
int i;
for (i = 0; i < fInside.Count(); i++)
{
if (fInside[i] == pActivateMsg->fHitterObj)
{
if (fIgnoreExtraEnters)
return false; // this is the "correct" way to handle this situation
break; // this is for those special situations where, due to some physics oddity, we need to allow the avatar to enter without exiting
}
}
if (i == fInside.Count())
fInside.Append(pActivateMsg->fHitterObj);
if (makeBriceHappyVar)
{
plSceneObject *pObj = plSceneObject::ConvertNoRef( pActivateMsg->fHitterObj->ObjectIsLoaded() );
if( pObj )
{
//need to check for human vs quabish type things in here
int i;
for( i = 0; i < pObj->GetNumModifiers(); i++ )
{
if (plArmatureMod::ConvertNoRef( pObj->GetModifier(i)))
{
if (plNetClientApp::GetInstance()->GetLocalPlayerKey() != pActivateMsg->fHitterObj)
{
plArmatureMod *am=const_cast<plArmatureMod*>( plArmatureMod::ConvertNoRef(pObj->GetModifier(i)));
if((am->IsLocalAI())==nil)
{
return false;
}
}
}
}
plSynchedObject* syncObj = (plSynchedObject*)pObj;
if (syncObj->IsLocallyOwned() != plSynchedObject::kYes)
{
return false;
}
}
}
if (fType == kTypeEnter)
{
fLogicMod->GetNotify()->AddCollisionEvent(true, pActivateMsg->fHitterObj, pActivateMsg->fHiteeObj, false);
//fLogicMod->RequestTrigger(false);
if (!Satisfied())
return false;
fLogicMod->Trigger(false);
}
return false;
}
else
if (pActivateMsg->fTriggerType == plActivatorMsg::kVolumeExit)
{
for (int i = 0; i < fInside.Count(); i++)
{
if (fInside[i] == pActivateMsg->fHitterObj)
{
fInside.Remove(i);
if (makeBriceHappyVar)
{
//need to check for human vs quabish type things in here
plSceneObject *pObj = plSceneObject::ConvertNoRef( pActivateMsg->fHitterObj->ObjectIsLoaded() );
if( pObj )
{
int i;
for( i = 0; i < pObj->GetNumModifiers(); i++ )
{
if (plArmatureMod::ConvertNoRef( pObj->GetModifier(i)))
{
if (plNetClientApp::GetInstance()->GetLocalPlayerKey() != pActivateMsg->fHitterObj)
{
plArmatureMod *am=const_cast<plArmatureMod*>( plArmatureMod::ConvertNoRef(pObj->GetModifier(i)));
if((am->IsLocalAI())==nil)
{
return false;
}
}
}
}
plSynchedObject* syncObj = (plSynchedObject*)pObj;
if (syncObj->IsLocallyOwned() != plSynchedObject::kYes)
{
return false;
}
}
}
if (fType == kTypeExit)
{
fLogicMod->GetNotify()->AddCollisionEvent(false, pActivateMsg->fHitterObj, pActivateMsg->fHiteeObj, false);
//fLogicMod->RequestTrigger(false);
if (!Satisfied())
return false;
fLogicMod->Trigger(false);
}
return false;
}
}
}
return false;
}
plPlayerPageMsg* page = plPlayerPageMsg::ConvertNoRef(msg);
if(page && page->fUnload)
{
for(int j= 0; j< fInside.Count(); j++)
{
if(fInside[j] == page->fPlayer)
{//this is the one inside
if(fHittee)
{
plSceneObject *so = plSceneObject::ConvertNoRef(fHittee->ObjectIsLoaded());
if(so && so->IsLocallyOwned())
{
if (fType == kTypeExit)
{
fLogicMod->GetNotify()->AddCollisionEvent(false, page->fPlayer, fHittee, false);
//fLogicMod->RequestTrigger(false);
if (!Satisfied())
return false;
fLogicMod->Trigger(false);
}
}
}
fInside.Remove(j);
}
}
}
return plConditionalObject::MsgReceive(msg);
}
void plVolumeSensorConditionalObjectNoArbitration::Read(hsStream* stream, hsResMgr* mgr)
{
plVolumeSensorConditionalObject::Read(stream, mgr);
plgDispatch::Dispatch()->RegisterForExactType(plPlayerPageMsg::Index(), GetKey());
}

View File

@ -0,0 +1,116 @@
/*==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 plObjectInBoxConditionalObject_inc
#define plObjectInBoxConditionalObject_inc
#include "../../NucleusLib/pnModifier/plConditionalObject.h"
#include "hsTemplates.h"
class plKey;
class plObjectInBoxConditionalObject : public plConditionalObject
{
protected:
hsTArray<plKey> fInside;
plKey fCurrentTrigger;
public:
plObjectInBoxConditionalObject();
~plObjectInBoxConditionalObject(){;}
CLASSNAME_REGISTER( plObjectInBoxConditionalObject );
GETINTERFACE_ANY( plObjectInBoxConditionalObject, plConditionalObject );
hsBool MsgReceive(plMessage* msg);
void Evaluate(){;}
void Reset() { SetSatisfied(false); }
virtual hsBool Satisfied() { return true; }
virtual hsBool Verify(plMessage* msg);
};
class plVolumeSensorConditionalObject : public plConditionalObject
{
protected:
hsTArray<plKey> fInside;
int fTrigNum;
int fType;
hsBool fFirst;
hsBool fTriggered;
hsBool fIgnoreExtraEnters;
public:
static bool makeBriceHappyVar;
enum
{
kTypeEnter = 1,
kTypeExit,
};
plVolumeSensorConditionalObject();
~plVolumeSensorConditionalObject(){;}
CLASSNAME_REGISTER( plVolumeSensorConditionalObject );
GETINTERFACE_ANY( plVolumeSensorConditionalObject, plConditionalObject );
virtual hsBool MsgReceive(plMessage* msg);
void Evaluate(){;}
void Reset() { SetSatisfied(false); }
virtual hsBool Satisfied();
void SetType(int i) { fType = i; }
void SetTrigNum(int i) { fTrigNum = i; }
void SetFirst(hsBool b) { fFirst = b; }
void IgnoreExtraEnters(hsBool ignore = true) {fIgnoreExtraEnters = ignore;}
virtual void Read(hsStream* stream, hsResMgr* mgr);
virtual void Write(hsStream* stream, hsResMgr* mgr);
};
class plVolumeSensorConditionalObjectNoArbitration : public plVolumeSensorConditionalObject
{
public:
plVolumeSensorConditionalObjectNoArbitration ():plVolumeSensorConditionalObject(){;}
~plVolumeSensorConditionalObjectNoArbitration (){;}
CLASSNAME_REGISTER( plVolumeSensorConditionalObjectNoArbitration );
GETINTERFACE_ANY( plVolumeSensorConditionalObjectNoArbitration, plConditionalObject );
virtual hsBool MsgReceive(plMessage* msg);
virtual void Read(hsStream* stream, hsResMgr* mgr);
protected:
plKey fHittee;
};
#endif // plObjectInBoxConditionalObject_inc

View File

@ -0,0 +1,52 @@
/*==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 "plObjectIntersectPlaneConditionalObject.h"
#include "../../PubUtilLib/plPhysical/plDetectorModifier.h"
#include "../../NucleusLib/pnModifier/plLogicModBase.h"
plObjectIntersectPlaneConditionalObject::plObjectIntersectPlaneConditionalObject()
{
}
hsBool plObjectIntersectPlaneConditionalObject::MsgReceive(plMessage* msg)
{
/*
if our target is within the bounds of the object our logic modifier is attached to...
{
bSatisfied = true;
fLogicMod->RequestTrigger();
return true;
}
*/
return plConditionalObject::MsgReceive(msg);
}

View File

@ -0,0 +1,58 @@
/*==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 plObjectIntersectPlaneConditionalObject_inc
#define plObjectIntersectPlaneConditionalObject_inc
#include "../../NucleusLib/pnModifier/plConditionalObject.h"
class plKey;
class plObjectIntersectPlaneConditionalObject : public plConditionalObject
{
protected:
plKey fTarget;
plKey fPlane;
public:
plObjectIntersectPlaneConditionalObject();
~plObjectIntersectPlaneConditionalObject(){;}
CLASSNAME_REGISTER( plObjectIntersectPlaneConditionalObject );
GETINTERFACE_ANY( plObjectIntersectPlaneConditionalObject, plConditionalObject );
hsBool MsgReceive(plMessage* msg);
void SetTarget(plKey pKey) { fTarget = pKey; }
void SetPlane(plKey pKey) { fPlane = pKey; }
void Evaluate(){;}
void Reset() { SetSatisfied(false); }
};
#endif // plObjectIntersectPlaneConditionalObject_inc

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==*/
#include "hsTypes.h"
#include "plPickedConditionalObject.h"
#include "../../PubUtilLib/plPhysical/plDetectorModifier.h"
#include "../../NucleusLib/pnModifier/plLogicModBase.h"
#include "../plMessage/plActivatorMsg.h"
plPickedConditionalObject::plPickedConditionalObject()
{
SetFlag(kLocalElement); // since it relies on user input
}
hsBool plPickedConditionalObject::MsgReceive(plMessage* msg)
{
plActivatorMsg* pDetectorMsg = plActivatorMsg::ConvertNoRef(msg);
if (pDetectorMsg && pDetectorMsg->TriggerType() == plActivatorMsg::kPickedTrigger )
{
SetSatisfied(true);
// fLogicMod->RequestTrigger();
return true;
}
return plConditionalObject::MsgReceive(msg);
}

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 plPickedConditionalObject_inc
#define plPickedConditionalObject_inc
#include "../../NucleusLib/pnModifier/plConditionalObject.h"
class plKey;
class plPickedConditionalObject : public plConditionalObject
{
protected:
public:
plPickedConditionalObject();
~plPickedConditionalObject(){;}
CLASSNAME_REGISTER( plPickedConditionalObject );
GETINTERFACE_ANY( plPickedConditionalObject, plConditionalObject );
hsBool MsgReceive(plMessage* msg);
void Evaluate(){;}
void Reset() { SetSatisfied(false); }
};
#endif // plPickedConditionalObject_inc

View File

@ -0,0 +1,924 @@
/*==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==*/
//////////////////////////////////////////////////////////////////////////////
// //
// Avatar Console Commands and Groups //
// //
//////////////////////////////////////////////////////////////////////////////
#ifdef PLASMA_EXTERNAL_RELEASE
#define LIMIT_CONSOLE_COMMANDS 1
#endif
#include "pfConsoleCmd.h"
#include "plgDispatch.h"
#include "pfConsole.h"
#include "hsResMgr.h"
#include "../pfMessage/plArmatureEffectMsg.h"
#include "../plMessage/plOneShotMsg.h"
#include "../plMessage/plAvatarMsg.h"
#include "../plMessage/plInputEventMsg.h"
#include "../plMessage/plSimStateMsg.h"
#include "../plMessage/plCCRMsg.h"
#include "../plMessage/plLinkToAgeMsg.h"
#include "../pnMessage/plNotifyMsg.h"
#include "../plModifier/plSpawnModifier.h"
#include "../plResMgr/plKeyFinder.h"
#include "../plAvatar/plArmatureMod.h"
#include "../plAvatar/plAvBrainCritter.h"
#include "../plAvatar/plAvBrainHuman.h"
#include "../plAvatar/plAvBrainSwim.h"
#include "../plAvatar/plAvBrainGeneric.h"
#include "../plAvatar/plAvatarMgr.h"
#include "../plAvatar/plSeekPointMod.h"
#include "../plAvatar/plOneShotMod.h"
#include "../plAvatar/plAGAnim.h"
#include "../plAvatar/plAvBrainUser.h"
#include "../plAvatar/plAvBrainHuman.h"
#include "../plAvatar/plNPCSpawnMod.h"
#include "../plAvatar/plAGAnimInstance.h"
#include "../plAvatar/plArmatureEffects.h"
#include "../plAvatar/plAvTaskSeek.h"
//#include "../plHavok1/plSimulationMgr.h"
#include "../pnNetCommon/plNetApp.h"
#include "../plNetClient/plNetClientMgr.h"
#include "../plDrawable/plInstanceDrawInterface.h"
#include "../plDrawable/plDrawableSpans.h"
#define PF_SANITY_CHECK( cond, msg ) { if( !( cond ) ) { PrintString( msg ); return; } }
//// This is here so Microsoft VC won't decide to "optimize" this file out
void pfConsoleCmdGroup::DummyAvatar( void )
{
}
/////////////////////////////////////////////////////////////////
//
// Please see pfConsoleCommands.cpp for detailed instructions on
// how to add console commands.
//
/////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////
//
// UTILITIES - LOCAL AND OTHERWISE
//
/////////////////////////////////////////////////////////////////
plKey FindSceneObjectByName(const char* name, const char* ageName, char* statusStr, bool subString=false);
plKey FindObjectByName(const char* name, int type, const char* ageName, char* statusStr, bool subString=false);
plKey FindObjectByNameAndType(const char* name, const char* typeName, const char* ageName,
char* statusStr, bool subString=false);
void PrintStringF(void pfun(const char *),const char * fmt, ...);
PF_CONSOLE_GROUP( Avatar )
#ifndef LIMIT_CONSOLE_COMMANDS
PF_CONSOLE_SUBGROUP( Avatar, Spawn )
PF_CONSOLE_SUBGROUP( Avatar, Multistage )
PF_CONSOLE_SUBGROUP( Avatar, X ) // experimental stuff
PF_CONSOLE_SUBGROUP( Avatar, Climb )
PF_CONSOLE_SUBGROUP( Avatar, Turn ) // Turning config
PF_CONSOLE_SUBGROUP( Avatar, Physics )
PF_CONSOLE_SUBGROUP( Avatar, Warp )
PF_CONSOLE_SUBGROUP( Avatar, Anim ) // anim commands
PF_CONSOLE_SUBGROUP( Avatar, AG ) // animation graph stuff
PF_CONSOLE_SUBGROUP( Avatar, LOD )
#endif // LIMIT_CONSOLE_COMMANDS
#include "../plAvatar/plAnimStage.h"
plAvBrainHuman * GetMainAvatarBrain()
{
plArmatureMod *avatar = plAvatarMgr::GetInstance()->GetLocalAvatar();
if(avatar)
{
plAvBrainHuman *brain = plAvBrainHuman::ConvertNoRef(avatar->GetBrain(0));
if(brain)
return brain;
}
return nil;
}
/////////////////////////////////////////////////////////////////////////////////////////
//
// THE COMMANDS
//
/////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////
//
// SPAWNING
//
/////////////////////////////////////////////////////////////////////////////////////////
#ifndef LIMIT_CONSOLE_COMMANDS
PF_CONSOLE_CMD( Avatar_Spawn, Show, "", "Print a list of spawn points.")
{
plAvatarMgr *mgr = plAvatarMgr::GetInstance();
int n = mgr->NumSpawnPoints();
for (int i = 0; i < n; i++)
{
const plSpawnModifier * spawn = mgr->GetSpawnPoint(i);
if(spawn)
{
PrintStringF(PrintString, "%d. %s", i, spawn->GetKey()->GetName());
}
}
}
PF_CONSOLE_CMD( Avatar_Spawn, Go, "int which", "Go a spawn point indicated by number.")
{
plAvatarMgr *mgr = plAvatarMgr::GetInstance();
int n = params[0];
int max = mgr->NumSpawnPoints();
if(n < max)
{
plArmatureMod *avatar = plAvatarMgr::GetInstance()->GetLocalAvatar();
if (avatar)
{
double fakeTime = 0.0f;
avatar->SpawnAt(n, fakeTime);
}
}
}
static int whichSpawn = 0;
PF_CONSOLE_CMD( Avatar_Spawn, next, "", "Go to the next spawn point in sequence.")
{
plAvatarMgr *mgr = plAvatarMgr::GetInstance();
int max = mgr->NumSpawnPoints();
whichSpawn = ++whichSpawn < max ? whichSpawn : 0;
plArmatureMod *avatar = plAvatarMgr::GetInstance()->GetLocalAvatar();
if(avatar)
{
PrintStringF(PrintString, "Spawning at point %d", whichSpawn);
double fakeTime = 0.0f;
avatar->SpawnAt(whichSpawn, fakeTime);
}
}
PF_CONSOLE_CMD( Avatar_Spawn, prev, "", "Go to the prev spawn point in sequence.")
{
plAvatarMgr *mgr = plAvatarMgr::GetInstance();
int max = mgr->NumSpawnPoints();
whichSpawn= --whichSpawn >= 0 ? whichSpawn: max-1;
plArmatureMod *avatar = plAvatarMgr::GetInstance()->GetLocalAvatar();
if(avatar)
{
PrintStringF(PrintString, "Spawning at point %d", whichSpawn);
double fakeTime = 0.0f;
avatar->SpawnAt(whichSpawn, fakeTime);
}
}
PF_CONSOLE_CMD( Avatar_Spawn, Respawn,"", "Moves the avatar back to the start point.")
{
plArmatureMod *avatar = plAvatarMgr::GetInstance()->GetLocalAvatar();
if (avatar)
{
avatar->Spawn(0);
}
}
PF_CONSOLE_CMD( Avatar_Spawn, SetSpawnOverride, "string spawnPointName", "Overrides the normal spawn point choice to be the object specified.")
{
plArmatureMod::SetSpawnPointOverride( (const char *)params[ 0 ] );
char str1[ 512 ];
sprintf( str1, "Spawn point override set to object %s", (const char *)params[ 0 ] );
PrintString( str1 );
}
PF_CONSOLE_CMD( Avatar_Spawn, DontPanic,"", "Toggles the Don't panic link flag.")
{
plArmatureMod *avatar = plAvatarMgr::GetInstance()->GetLocalAvatar();
if (avatar)
{
bool state = avatar->ToggleDontPanicLinkFlag();
char str1[256];
sprintf(str1, "DontPanic set to %s", state?"true":"false");
PrintString( str1 );
}
}
/////////////////////////////////////////////////////////////////////////////////////////
//
// TURN TUNING
//
/////////////////////////////////////////////////////////////////////////////////////////
PF_CONSOLE_CMD( Avatar_Turn, GetMaxTurn, "int walk", "Show the maximum turn speed in radians per second.")
{
plAvBrainHuman *brain = GetMainAvatarBrain();
float maxTurn = brain->GetMaxTurnSpeed((int)params[0] != 0);
PrintStringF(PrintString, "Avatar max turn speed is %f radians per second.", maxTurn);
}
PF_CONSOLE_CMD( Avatar_Turn, SetMaxTurn, "float maxTurn, int walk", "Set the maximum turn speed in radians per second.")
{
plAvBrainHuman *brain = GetMainAvatarBrain();
float newMaxTurn = params[0];
brain->SetMaxTurnSpeed(newMaxTurn, (int)params[1] != 0);
PrintStringF(PrintString, "Set the avatar max turn speed to %f radians per second.", newMaxTurn);
}
// TURN TIME
PF_CONSOLE_CMD( Avatar_Turn, GetTurnTime, "int walk", "Show the amount of time required to reach max turn speed.")
{
plAvBrainHuman *brain = GetMainAvatarBrain();
float turnTime = brain->GetTimeToMaxTurn((int)params[0] != 0);
PrintStringF(PrintString, "The amount of time required to reach max avatar turn speed is %f seconds.", turnTime);
}
PF_CONSOLE_CMD( Avatar_Turn, SetTurnTime, "float turnTime, int walk", "Set the amount of time required to reach max turn speed.")
{
plAvBrainHuman *brain = GetMainAvatarBrain();
float newTurnTime = params[0];
brain->SetTimeToMaxTurn(newTurnTime, (int)params[1] != 0);
PrintStringF(PrintString, "Set the amount of time required to reach max avatar turn speed to %f seconds.", newTurnTime);
}
// TURN TYPE
PF_CONSOLE_CMD( Avatar_Turn, GetTurnType, "int walk", "Show the amount of time required to reach max turn speed.")
{
plAvBrainHuman *brain = GetMainAvatarBrain();
int turnType = brain->GetTurnCurve((int)params[0] != 0);
PrintStringF(PrintString, "The avatar turn curve type is %d.", turnType);
}
PF_CONSOLE_CMD( Avatar_Turn, SetTurnType, "int turnType, int walk", "Set the turn acceleration curve type [0..2].")
{
plAvBrainHuman *brain = GetMainAvatarBrain();
int newCurveType = params[0];
brain->SetTurnCurve(plAvBrainHuman::TurnCurve(newCurveType), (int)params[1] != 0);
PrintStringF(PrintString, "Set turn curve to %d.", newCurveType);
}
PF_CONSOLE_CMD( Avatar_Turn, SetMouseTurnSensitivity, "float sensitivity", "Set how strong the mouse affects turning.")
{
plArmatureMod::SetMouseTurnSensitivity(params[0]);
PrintStringF(PrintString, "Set mouse sensitivity to %f", (float)params[0]);
}
/////////////////////////////////////////////////////////////////////////////////////////
//
// MULTISTAGE
//
/////////////////////////////////////////////////////////////////////////////////////////
// MULTISTAGE.TRIGGER
PF_CONSOLE_CMD( Avatar_Multistage, Trigger, "string multiComp", "Triggers the named Multistage Animation component")
{
char str[256];
plKey key = FindObjectByNameAndType((const char*)params[0], "plMultistageBehMod", nil, str, true);
PrintString(str);
if (key)
{
plNotifyMsg *msg = TRACKED_NEW plNotifyMsg;
msg->fType = plNotifyMsg::kActivator;
msg->fState = 1; // Triggered
// Setup the event data in case this is a OneShot responder that needs it
plKey playerKey = plAvatarMgr::GetInstance()->GetLocalAvatar()->GetKey();
proPickedEventData *ed = TRACKED_NEW proPickedEventData;
ed->fPicker = playerKey;
ed->fPicked = key; // ???
msg->AddEvent(ed);
// Send it to the responder modifier
msg->AddReceiver(key);
plgDispatch::MsgSend(msg);
}
}
// MULTISTAGE.ADVANCE
PF_CONSOLE_CMD( Avatar_Multistage, Advance, "", "Advances the avatar's current multistage to the next stage.")
{
plArmatureMod *avatar = plAvatarMgr::GetInstance()->GetLocalAvatar();
if (avatar)
{
plKey avKey = avatar->GetKey();
plAvBrainGenericMsg *msg = TRACKED_NEW plAvBrainGenericMsg(nil, avKey, plAvBrainGenericMsg::kNextStage, 0, true, 0.5f);
msg->Send();
}
}
// MULTISTAGE.REGRESS
PF_CONSOLE_CMD( Avatar_Multistage, Regress, "", "Regresses the avatar's current multistage to the previous stage.")
{
plArmatureMod *avatar = plAvatarMgr::GetInstance()->GetLocalAvatar();
if (avatar)
{
plKey avKey = avatar->GetKey();
plAvBrainGenericMsg *msg = TRACKED_NEW plAvBrainGenericMsg(nil, avKey, plAvBrainGenericMsg::kPrevStage, 0, true, 0.5f);
msg->Send();
}
}
PF_CONSOLE_CMD( Avatar_Multistage, Mode, "string stage1, string stage2, string stage3", "make a simple multistage")
{
plArmatureMod *avatar = plAvatarMgr::GetInstance()->GetLocalAvatar();
const char *one = params[0];
const char *two = params[1];
const char *three = params[2];
PushSimpleMultiStage(avatar, one, two, three, true, true, plAGAnim::kBodyFull);
}
/////////////////////////////////////////////////////////////////////////////////////////
//
// MISCKELANYOUS
//
/////////////////////////////////////////////////////////////////////////////////////////
PF_CONSOLE_CMD( Avatar, Debug, "", "Toggle the avatar debug display.")
{
static int toggle = 0;
plArmatureMod *avatar = plAvatarMgr::GetInstance()->GetLocalAvatar();
if(avatar)
{
toggle = toggle ? 0 : 1;
avatar->SetDebugState(toggle);
}
}
PF_CONSOLE_CMD( Avatar, DebugByID, "int PlayerID", "Show debug display for a specific avatar.")
{
plArmatureMod *avatar = plAvatarMgr::GetInstance()->FindAvatarByPlayerID((int)params[0]);
if (avatar)
{
avatar->SetDebugState(!avatar->GetDebugState());
}
}
PF_CONSOLE_CMD( Avatar, LogSmartSeek, "int enabled", "Enable/Disable smart seek logging (avatar.log)")
{
plAvTaskSeek::fLogProcess = ((int)params[0] == 1);
}
PF_CONSOLE_CMD( Avatar, PopBrain, "", "Remove the topmost brain from the avatar. Careful there, sport.")
{
plArmatureMod *avatar = plAvatarMgr::GetInstance()->GetLocalAvatar();
if(avatar)
{
avatar->PopBrain();
}
}
#include "../plScene/plRelevanceMgr.h"
PF_CONSOLE_CMD( Avatar,
MarkRelevanceRegion,
"string regionA, string regionB, int wantsUpdate",
"Mark whether avatars in regionA want updates on those on regionB" )
{
plRelevanceMgr *mgr = plRelevanceMgr::Instance();
char *regA = params[0];
char *regB = params[1];
mgr->MarkRegion(mgr->GetIndex(regA), mgr->GetIndex(regB), params[2]);
}
PF_CONSOLE_CMD( Avatar,
ToggleRelevanceRegions,
"",
"Enable/Disable all relevance regions" )
{
plRelevanceMgr *mgr = plRelevanceMgr::Instance();
mgr->SetEnabled(!mgr->GetEnabled());
char buff[256];
sprintf(buff, "All relevance regions are now %s", (mgr->GetEnabled() ? "ENABLED" : "DISABLED"));
PrintString(buff);
}
PF_CONSOLE_CMD( Avatar, SeekPoint, "string seekpoint", "Move to the given seekpoint.")
{
char *spName = params[0];
plArmatureMod *avatar = plAvatarMgr::GetInstance()->GetLocalAvatar();
if(avatar)
{
char buff[256];
plKey seekKey = FindSceneObjectByName(spName, nil, buff);
plSeekPointMod *mod = plAvatarMgr::GetInstance()->FindSeekPoint(spName);
if(mod)
{
plKey seekKey = mod->GetKey();
plSeekPointMod *seekMod = (plSeekPointMod *)seekKey->GetObjectPtr();
plSceneObject *seekTarget = seekMod->GetTarget(0);
plKey targetKey = seekTarget->GetKey();
plKey avKey = avatar->GetKey();
hsScalar unused = 0.0f;
plAvSeekMsg *msg = TRACKED_NEW plAvSeekMsg(nil, avKey, targetKey, unused, false);
plgDispatch::MsgSend(msg);
}
}
}
PF_CONSOLE_CMD( Avatar, ShowLocations, "", "Show player positions/orientations" )
{
hsBool curVal = plNetClientApp::GetInstance()->GetFlagsBit(plNetClientApp::kShowAvatars);
plNetClientApp::GetInstance()->SetFlagsBit(plNetClientApp::kShowAvatars, !curVal);
}
PF_CONSOLE_CMD( Avatar,
SetFootEffect,
"int group",
"Force the avatar to use certain footstep effects" )
{
const plArmatureMod *avMod = plAvatarMgr::GetInstance()->GetLocalAvatar();
if (avMod)
{
plArmatureEffectStateMsg *msg = TRACKED_NEW plArmatureEffectStateMsg();
msg->AddReceiver(avMod->GetArmatureEffects()->GetKey());
msg->fSurface = (int)params[0];
plgDispatch::MsgSend(msg);
}
}
PF_CONSOLE_CMD( Avatar, SetStealthMode, "int mode", "Set the stealth mode of your avatar.")
{
const plArmatureMod *avMod = plAvatarMgr::GetInstance()->GetLocalAvatar();
if (avMod)
{
int mode=params[0];
plKey avKey=avMod->GetTarget(0)->GetKey();
int level = mode==plAvatarStealthModeMsg::kStealthVisible ? 0 : 1;
// send msg to make myself invisible locally
plAvatarStealthModeMsg *msg = TRACKED_NEW plAvatarStealthModeMsg();
msg->SetSender(avKey);
msg->fMode = mode;
msg->fLevel = level;
plgDispatch::MsgSend(msg);
// send net msg to other players to synch them up
// the msg will go to their NetClientMgr who will decide whether they see
// our avatar as total or semi-invisible based on the invis level.
plCCRInvisibleMsg *invisMsg = TRACKED_NEW plCCRInvisibleMsg; // ctor sets flags and receiver
invisMsg->fInvisLevel=level;
invisMsg->fAvKey=avKey;
invisMsg->Send();
}
}
PF_CONSOLE_CMD( Avatar, SortFaces, "", "Toggle sorting of polys on the avatar" )
{
const plArmatureMod *avMod = plAvatarMgr::GetInstance()->GetLocalAvatar();
const plSceneObject *so = avMod->GetClothingSO(0);
plInstanceDrawInterface *idi = plInstanceDrawInterface::ConvertNoRef(const_cast<plDrawInterface*>(so->GetDrawInterface()));
plDrawableSpans *drawable = idi->GetInstanceDrawable();
drawable->SetNativeProperty(plDrawable::kPropSortFaces, !drawable->GetNativeProperty(plDrawable::kPropSortFaces));
}
#endif // LIMIT_CONSOLE_COMMANDS
PF_CONSOLE_CMD( Avatar, SetMouseTurnSensitivity, "float sensitivity", "Set how strong the mouse affects turning.")
{
plArmatureMod::SetMouseTurnSensitivity(params[0]);
PrintStringF(PrintString, "Set mouse sensitivity to %f", (float)params[0]);
}
PF_CONSOLE_CMD( Avatar, ClickToTurn, "bool b", "Set click-to-turn functionality.")
{
bool b = params[0];
plArmatureMod::fClickToTurn = b;
}
PF_CONSOLE_CMD( Avatar, FakeLinkToObj, "string objName", "Pseudo-Link the avatar to the specified object's location")
{
char *spName = params[0];
char buff[256];
plKey seekKey = FindSceneObjectByName(spName, nil, buff);
if (!seekKey)
{
PrintString("Can't find object with that name, fake link failed.");
return;
}
plPseudoLinkEffectMsg* msg = TRACKED_NEW plPseudoLinkEffectMsg;
msg->fAvatarKey = plNetClientMgr::GetInstance()->GetLocalPlayerKey();
msg->fLinkObjKey = seekKey;
plgDispatch::MsgSend(msg);
}
#ifndef LIMIT_CONSOLE_COMMANDS
///////////////////////////////////////////////////////////////////////////////////////////////////
//
// PHYSICS
//
///////////////////////////////////////////////////////////////////////////////////////////////////
PF_CONSOLE_CMD( Avatar_Physics, TogglePhysical, "", "Disable/enable physics on the avatar.")
{
plArmatureMod *avatar = plAvatarMgr::GetInstance()->GetLocalAvatar();
if(avatar)
{
plControlEventMsg* pMsg = TRACKED_NEW plControlEventMsg;
pMsg->SetControlActivated(true);
pMsg->SetControlCode(B_CONTROL_TOGGLE_PHYSICAL);
avatar->MsgReceive(pMsg);
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
//
// Animation
//
///////////////////////////////////////////////////////////////////////////////////////////////////
PF_CONSOLE_CMD( Avatar_Anim, BlendAnim, "string Animation, float blendFactor", "Blend the given animation with the current animation.")
{
char *animationName = params[0];
float blendFactor = params[1];
plArmatureMod *avatar = plAvatarMgr::GetInstance()->GetLocalAvatar();
if (avatar && animationName)
{
plAGAnim * anim = plAGAnim::FindAnim(animationName);
if(anim)
{
plAGAnimInstance * inst = avatar->AttachAnimationBlended(animationName, blendFactor);
inst->SetLoop(true);
} else
PrintString("BlendAnim: Couldn't find animation.");
}
}
PF_CONSOLE_CMD( Avatar_Anim, BlendAnimPri, "string Animation, float blendFactor, int priority", "Blend animation using priority.")
{
char *animationName = params[0];
float blendFactor = params[1];
int priority = params[2];
plArmatureMod *avatar = plAvatarMgr::GetInstance()->GetLocalAvatar();
if (avatar && animationName)
{
plAGAnim * anim = plAGAnim::FindAnim(animationName);
if(anim)
{
plAGAnimInstance * inst = avatar->AttachAnimationBlended(animationName, blendFactor, priority);
inst->SetLoop(true);
} else
PrintString("BlendAnim: Couldn't find animation.");
}
}
PF_CONSOLE_CMD( Avatar_Anim, PlaySimpleAnim, "string AvatarName, string Animation", "Play a simple (root not animated) one time animation on the avatar")
{
plArmatureMod *avatar = plAvatarMgr::GetInstance()->FindAvatarByModelName(params[0]);
if (avatar)
avatar->PlaySimpleAnim(params[1]);
}
PF_CONSOLE_CMD( Avatar_Anim, DetachAnim, "string Animation", "Remove the given animation from the avatar.")
{
char *animationName = params[0];
plArmatureMod *avatar = plAvatarMgr::GetInstance()->GetLocalAvatar();
if (avatar && animationName)
{
plAGAnimInstance * instance = avatar->FindAnimInstance(animationName);
if(instance)
avatar->DetachAnimation(instance);
else
PrintString("DetachAnim: Couldn't find animation on avatar.");
}
}
PF_CONSOLE_CMD( Avatar_Anim, SetBlend, "string Animation, float blend", "Set the blend of the given animation.")
{
char *animationName = params[0];
float blend = params[1];
plArmatureMod *avatar = plAvatarMgr::GetInstance()->GetLocalAvatar();
if (avatar && animationName)
{
plAGAnimInstance *anim = avatar->FindAnimInstance(animationName);
if(anim)
anim->SetBlend(blend);
else
PrintString("SetBlend: Couldn't find animation.");
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
//
// LOD
//
///////////////////////////////////////////////////////////////////////////////////////////////////
PF_CONSOLE_CMD( Avatar_LOD, SetLOD, "int lod", "Show only the selected LOD.")
{
plArmatureMod *avatar = plAvatarMgr::GetInstance()->GetLocalAvatar();
if(avatar)
{
plArmatureLODMod *lodder = plArmatureLODMod::ConvertNoRef(avatar);
if(lodder)
{
int lod = params[0];
lodder->SetLOD(lod);
} else {
PrintString("SetLOD: found avatar, but it doesn't support LOD.");
}
} else {
PrintString("SetLOD: couldn't find avatar with that name.");
}
}
PF_CONSOLE_CMD( Avatar_LOD, LimitLOD, "int newLOD", "Zero is (always) highest detail; 2 is (currently) lowest." )
{
int newLOD = params[0];
if(newLOD >= 0 && newLOD <= 2)
plArmatureLODMod::fMinLOD = newLOD;
}
PF_CONSOLE_CMD( Avatar_LOD, SetLODDistance, "float newDist", "Set Distance for switching Avatar LOD" )
{
plArmatureLODMod::fLODDistance = float(params[0]);
}
PF_CONSOLE_CMD( Avatar_LOD, GetLODDistance, "", "Get Distance for switching Avatar LOD" )
{
char buffer[256];
sprintf(buffer, "Lod Distance = %f", plArmatureLODMod::fLODDistance);
PrintString(buffer);
}
///////////////////////////////////////////////////////////////////////////////////////////////////
//
// CLIMBING
//
///////////////////////////////////////////////////////////////////////////////////////////////////
#include "../plAvatar/plAvBrainClimb.h"
PF_CONSOLE_CMD( Avatar_Climb, Start, "string direction", "Specify initial mount direction: up, down, left, right")
{
plArmatureMod *avMod = const_cast<plArmatureMod *>(plAvatarMgr::GetInstance()->GetLocalAvatar());
if(avMod)
{
const char *dirStr = params[0];
plAvBrainClimb::Mode mode;
if(stricmp(dirStr, "up") == 0)
mode = plAvBrainClimb::kMountingUp;
else if(stricmp(dirStr, "down") == 0)
mode = plAvBrainClimb::kMountingDown;
else if(stricmp(dirStr, "left") == 0)
mode = plAvBrainClimb::kMountingLeft;
else if(stricmp(dirStr, "right") == 0)
mode = plAvBrainClimb::kMountingRight;
plAvBrainClimb *brain = TRACKED_NEW plAvBrainClimb(mode);
avMod->PushBrain(brain);
}
}
PF_CONSOLE_CMD( Avatar_Climb, EnableDismount, "string direction", "Let the avatar dismount in the specified direction.")
{
plArmatureMod *avMod = const_cast<plArmatureMod *>(plAvatarMgr::GetInstance()->GetLocalAvatar());
if(avMod)
{
plKey mgr = plAvatarMgr::GetInstance()->GetKey();
plKey avKey = avMod->GetKey();
const char *dirStr = params[0];
plClimbMsg::Direction dir;
if(stricmp(dirStr, "up") == 0)
dir = plClimbMsg::kUp;
else if(stricmp(dirStr, "down") == 0)
dir = plClimbMsg::kDown;
else if(stricmp(dirStr, "left") == 0)
dir = plClimbMsg::kLeft;
else if(stricmp(dirStr, "right") == 0)
dir = plClimbMsg::kRight;
plClimbMsg *msg = TRACKED_NEW plClimbMsg(mgr, avKey, plClimbMsg::kEnableDismount, dir, true);
msg->Send();
}
}
PF_CONSOLE_CMD( Avatar_Climb, EnableClimb, "string direction, int onOff", "Allow or forbid climbing in the given direction.")
{
plArmatureMod *avMod = const_cast<plArmatureMod *>(plAvatarMgr::GetInstance()->GetLocalAvatar());
if(avMod)
{
plKey mgr = plAvatarMgr::GetInstance()->GetKey();
plKey avKey = avMod->GetKey();
const char *dirStr = params[0];
plClimbMsg::Direction dir;
if(stricmp(dirStr, "up") == 0)
dir = plClimbMsg::kUp;
else if(stricmp(dirStr, "down") == 0)
dir = plClimbMsg::kDown;
else if(stricmp(dirStr, "left") == 0)
dir = plClimbMsg::kLeft;
else if(stricmp(dirStr, "right") == 0)
dir = plClimbMsg::kRight;
hsBool enable = static_cast<int>(params[1]) ? true : false;
plClimbMsg *msg = TRACKED_NEW plClimbMsg(mgr, avKey, plClimbMsg::kEnableClimb, dir, enable);
msg->Send();
}
}
PF_CONSOLE_CMD( Avatar_Climb, Release, "", "")
{
plArmatureMod *avMod = const_cast<plArmatureMod *>(plAvatarMgr::GetInstance()->GetLocalAvatar());
if(avMod)
{
plKey mgr = plAvatarMgr::GetInstance()->GetKey();
plKey avKey = avMod->GetKey();
plClimbMsg *msg = TRACKED_NEW plClimbMsg(mgr, avKey, plClimbMsg::kRelease);
msg->Send();
}
}
PF_CONSOLE_CMD( Avatar_Climb, FallOff, "", "")
{
plArmatureMod *avMod = plAvatarMgr::GetInstance()->GetLocalAvatar();
if(avMod)
{
plKey mgr = plAvatarMgr::GetInstance()->GetKey();
plKey avKey = avMod->GetKey();
plClimbMsg *msg = TRACKED_NEW plClimbMsg(mgr, avKey, plClimbMsg::kFallOff);
msg->Send();
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// SWIMMING
//
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
PF_CONSOLE_SUBGROUP( Avatar, Swim )
PF_CONSOLE_CMD( Avatar_Swim, Start, "", "")
{
plArmatureMod *avMod = const_cast<plArmatureMod*>(plAvatarMgr::GetInstance()->GetLocalAvatar());
if(avMod)
{
plAvBrainSwim * brayne = TRACKED_NEW plAvBrainSwim();
avMod->PushBrain(brayne);
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
//
// WARP
//
///////////////////////////////////////////////////////////////////////////////////////////////////
// void WarpPlayerToAnother(hsBool iMove, UInt32 remoteID)
PF_CONSOLE_CMD( Avatar_Warp, WarpToPlayer, "int PlayerID", "Warp our player to the same position as another player.")
{
plAvatarMgr::WarpPlayerToAnother(true, (int)params[0]);
}
PF_CONSOLE_CMD( Avatar_Warp, WarpPlayerHere, "int PlayerID", "Warp another player to the same position as us.")
{
plAvatarMgr::WarpPlayerToAnother(false, (int)params[0]);
}
PF_CONSOLE_CMD( Avatar_Warp, WarpToXYZ, "float x, float y, float z", "Warp our avatar to the given location.")
{
plAvatarMgr::WarpPlayerToXYZ((float)params[0], (float)params[1], (float)params[2]);
}
///////////////////////////////////////////////////////////////////////////////////////////////////
//
// AG (Animation Graph)
//
///////////////////////////////////////////////////////////////////////////////////////////////////
#include "hsTimer.h"
PF_CONSOLE_CMD( Avatar_AG, DumpFull, "", "print out the animation graph for the avatar")
{
plArmatureMod *avatar = plAvatarMgr::GetInstance()->GetLocalAvatar();
double time = hsTimer::GetSysSeconds();
avatar->DumpAniGraph(nil, false, time);
}
PF_CONSOLE_CMD( Avatar_AG, DumpFullOptimized, "", "print out the optimized animation graph for the avatar")
{
plArmatureMod *avatar = plAvatarMgr::GetInstance()->GetLocalAvatar();
double time = hsTimer::GetSysSeconds();
avatar->DumpAniGraph(nil, true, time);
}
PF_CONSOLE_CMD( Avatar_AG, DumpSingle, "string boneName", "print out the animation graph for the given (avatar) bone")
{
plArmatureMod *avatar = plAvatarMgr::GetInstance()->GetLocalAvatar();
double time = hsTimer::GetSysSeconds();
const char *bone = params[0];
avatar->DumpAniGraph(bone, false, time);
}
PF_CONSOLE_CMD( Avatar_AG, DumpSingleOptimized, "string boneName", "print out the optimized animatoin graph for the given (avatar) bone")
{
plArmatureMod *avatar = plAvatarMgr::GetInstance()->GetLocalAvatar();
double time = hsTimer::GetSysSeconds();
const char *bone = params[0];
avatar->DumpAniGraph(bone, true, time);
}
#endif // LIMIT_CONSOLE_COMMANDS

View File

@ -0,0 +1,60 @@
/*==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==*/
//////////////////////////////////////////////////////////////////////////////
// //
// CCR Console Commands and Groups //
// These console commands are meant for use by customer care reps. //
// Eventually the functionality defined here will be accessed through a GUI//
// //
//////////////////////////////////////////////////////////////////////////////
//
// Only calls to the CCRMgr interface are allowed here
// See me if you need to include any other files...
//
#include "pfConsoleCmd.h"
#include "pfConsole.h"
#include "../pfCCR/plCCRMgr.h"
#include "../plNetClient/plNetClientMgr.h"
//// This is here so Microsoft VC won't decide to "optimize" this file out
// YOU ALSO NEED TO CALL THIS FXN
void pfConsoleCmdGroup::DummyCCR( void )
{
}
void PrintStringF(void pfun(const char *),const char * fmt, ...);
/////////////////////////////////////////////////////////////////
//
// Please see pfConsoleCommands.cpp for detailed instructions on
// how to add console commands.
//
/////////////////////////////////////////////////////////////////
#define PF_SANITY_CHECK( cond, msg ) { if( !( cond ) ) { PrintString( msg ); return; } }

View File

@ -0,0 +1,149 @@
/*==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==*/
//////////////////////////////////////////////////////////////////////////////
// //
// pfConsole Header //
// //
// 9.21.2001 mcn - Added pfLogDisplays. These are classes that represent //
// a scrolling buffer, much like the console, for on- //
// screen display of error logs and the such. Currently //
// managed by the console, but hopefully once we have //
// a general manager for dialogs/menus (debug or //
// otherwise), that manager will take the displays over. //
// //
//////////////////////////////////////////////////////////////////////////////
#ifndef _pfConsole_h
#define _pfConsole_h
#include "hsTypes.h"
#include "../pnKeyedObject/hsKeyedObject.h"
class plPipeline;
//// Class Definition ////////////////////////////////////////////////////////
class pfConsoleEngine;
class plKeyEventMsg;
class pfConsoleInputInterface;
class pfConsole : public hsKeyedObject
{
friend class pfConsoleInputInterface;
protected:
enum Konstants
{
kNumHistoryItems = 16,
kModeHidden = 0,
kModeSingleLine = 1,
kModeFull = 2,
kEffectDivisions = 1000,
kMaxCharsWide = 80,
kHelpDelay = 32,
kCursorBlinkRate = 16,
kMsgHintTimeout = 64,
kWorkingLineSize = 256
};
UInt32 fNumDisplayLines;
Int32 fEffectCounter;
float fLastTime;
UInt32 fHelpTimer;
char fLastHelpMsg[ kWorkingLineSize ];
UInt8 fMode; // 0 - invisible, 1 - single line, 2 - full
hsBool fInited, fHelpMode, fPythonMode, fPythonFirstTime, fFXEnabled;
UInt32 fPythonMultiLines;
short fCursorTicks;
UInt32 fMsgTimeoutTimer;
char fHistory[ kNumHistoryItems ][ kMaxCharsWide ];
UInt32 fHistoryCursor, fHistoryRecallCursor;
char *fDisplayBuffer;
char fWorkingLine[ kWorkingLineSize ];
UInt32 fWorkingCursor;
pfConsoleInputInterface *fInputInterface;
pfConsoleEngine *fEngine;
void IHandleKey( plKeyEventMsg *msg );
char IKeyEventToChar( plKeyEventMsg *msg );
static UInt32 fConsoleTextColor;
static pfConsole *fTheConsole;
static void _cdecl IAddLineCallback( const char *string );
static plPipeline *fPipeline;
void IAddLine( const char *string, short leftMargin = 0 );
void IAddParagraph( const char *string, short margin = 0 );
void IClear( void );
void ISetMode( UInt8 mode );
void IEnableFX( hsBool e ) { fFXEnabled = e; }
hsBool IFXEnabled( void ) { return fFXEnabled; }
void IPrintSomeHelp( void );
void IUpdateTooltip( void );
public:
pfConsole();
~pfConsole();
CLASSNAME_REGISTER( pfConsole );
GETINTERFACE_ANY( pfConsole, plReceiver );
static pfConsole * GetInstance ();
virtual hsBool MsgReceive( plMessage *msg );
void Init( pfConsoleEngine *engine );
void Draw( plPipeline *p );
static void AddLine( const char *string ) { fTheConsole->IAddParagraph( string ); }
static void AddLineF(const char * fmt, ...);
static void Clear( void ) { fTheConsole->IClear(); }
static void Hide( void ) { fTheConsole->ISetMode(kModeHidden); }
static void EnableEffects( hsBool enable ) { fTheConsole->IEnableFX( enable ); }
static hsBool AreEffectsEnabled( void ) { return fTheConsole->IFXEnabled(); }
static void SetTextColor( UInt32 color ) { fConsoleTextColor = color; }
static UInt32 GetTextColor() { return fConsoleTextColor; }
static void SetPipeline( plPipeline *pipe ) { fPipeline = pipe; }
static plPipeline *GetPipeline( void ) { return fPipeline; }
static void RunCommandAsync (const char cmd[]);
};
#endif //_pfConsole_h

View File

@ -0,0 +1,657 @@
/*==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==*/
//////////////////////////////////////////////////////////////////////////////
// //
// pfConsoleCmd Functions //
// //
//////////////////////////////////////////////////////////////////////////////
#include "pfConsoleCmd.h"
#include "hsUtils.h"
//////////////////////////////////////////////////////////////////////////////
//// pfConsoleCmdGroup Stuff /////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
pfConsoleCmdGroup *pfConsoleCmdGroup::fBaseCmdGroup = nil;
UInt32 pfConsoleCmdGroup::fBaseCmdGroupRef = 0;
//// Constructor & Destructor ////////////////////////////////////////////////
pfConsoleCmdGroup::pfConsoleCmdGroup( char *name, char *parent )
{
Dummy();
DummyJunior();
DummyNet();
DummyAvatar();
DummyCCR();
fNext = nil;
fPrevPtr = nil;
fCommands = nil;
fSubGroups = nil;
if( name == nil )
{
/// Create base
hsStrncpy( fName, "base", sizeof( fName ) );
fParentGroup = nil;
}
else
{
pfConsoleCmdGroup *group = GetBaseGroup();
if( parent != nil && parent[ 0 ] != 0 )
{
group = group->FindSubGroupRecurse( parent );
hsAssert( group != nil, "Trying to register group under nonexistant group!" );
}
hsStrncpy( fName, name, sizeof( fName ) );
group->AddSubGroup( this );
fParentGroup = group;
}
}
pfConsoleCmdGroup::~pfConsoleCmdGroup()
{
if( this != fBaseCmdGroup )
{
Unlink();
DecBaseCmdGroupRef();
}
}
//// GetBaseGroup ////////////////////////////////////////////////////////////
pfConsoleCmdGroup *pfConsoleCmdGroup::GetBaseGroup( void )
{
if( fBaseCmdGroup == nil )
{
/// Initialize base group
fBaseCmdGroup = TRACKED_NEW pfConsoleCmdGroup( nil, nil );
}
return fBaseCmdGroup;
}
//// DecBaseCmdGroupRef //////////////////////////////////////////////////////
void pfConsoleCmdGroup::DecBaseCmdGroupRef( void )
{
fBaseCmdGroupRef--;
if( fBaseCmdGroupRef == 0 )
{
delete fBaseCmdGroup;
fBaseCmdGroup = nil;
}
}
//// Add Functions ///////////////////////////////////////////////////////////
void pfConsoleCmdGroup::AddCommand( pfConsoleCmd *cmd )
{
cmd->Link( &fCommands );
fBaseCmdGroupRef++;
}
void pfConsoleCmdGroup::AddSubGroup( pfConsoleCmdGroup *group )
{
group->Link( &fSubGroups );
fBaseCmdGroupRef++;
}
//// FindCommand /////////////////////////////////////////////////////////////
// No longer recursive.
pfConsoleCmd *pfConsoleCmdGroup::FindCommand( char *name )
{
pfConsoleCmd *cmd;
hsAssert( name != nil, "nil name passed to FindCommand()" );
/// Only search locally
for( cmd = fCommands; cmd != nil; cmd = cmd->GetNext() )
{
if( strcmp( cmd->GetName(), name ) == 0 )
return cmd;
}
return nil;
}
//// FindNestedPartialCommand ////////////////////////////////////////////////
// Okay. YAFF. This one searches through the group and its children looking
// for a partial command based on the string given. The counter determines
// how many matches it skips before returning a match. (That way you can
// cycle through matches by sending 1 + the last counter every time).
pfConsoleCmd *pfConsoleCmdGroup::FindNestedPartialCommand( char *name, UInt32 *counter )
{
pfConsoleCmd *cmd;
pfConsoleCmdGroup *group;
hsAssert( name != nil, "nil name passed to FindNestedPartialCommand()" );
hsAssert( counter != nil, "nil counter passed to FindNestedPartialCommand()" );
// Try us
for( cmd = fCommands; cmd != nil; cmd = cmd->GetNext() )
{
if( _strnicmp( cmd->GetName(), name, strlen( name ) ) == 0 )
{
if( *counter == 0 )
return cmd;
(*counter)--;
}
}
// Try children
for( group = fSubGroups; group != nil; group = group->GetNext() )
{
cmd = group->FindNestedPartialCommand( name, counter );
if( cmd != nil )
return cmd;
}
return nil;
}
//// FindSubGroup ////////////////////////////////////////////////////////////
pfConsoleCmdGroup *pfConsoleCmdGroup::FindSubGroup( char *name )
{
pfConsoleCmdGroup *group;
hsAssert( name != nil, "nil name passed to FindSubGroup()" );
/// Only search locally
for( group = fSubGroups; group != nil; group = group->GetNext() )
{
if( strcmp( group->GetName(), name ) == 0 )
return group;
}
return nil;
}
//// FindSubGroupRecurse /////////////////////////////////////////////////////
// Resurces through a string, finding the final subgroup that the string
// represents. Parses with spaces, _ or . as the separators. Copies string.
pfConsoleCmdGroup *pfConsoleCmdGroup::FindSubGroupRecurse( const char *name )
{
char *ptr, *string;
pfConsoleCmdGroup *group;
static char seps[] = " ._";
string = TRACKED_NEW char[ strlen( name ) + 1 ];
hsAssert( string != nil, "Cannot allocate string in FindSubGroupRecurse()" );
strcpy( string, name );
/// Scan for subgroups
group = pfConsoleCmdGroup::GetBaseGroup();
ptr = strtok( string, seps );
while( ptr != nil )
{
// Take this token and check to see if it's a group
group = group->FindSubGroup( ptr );
hsAssert( group != nil, "Invalid group name to FindSubGroupRecurse()" );
ptr = strtok( nil, seps );
}
delete [] string;
return group;
}
//// FindCommandNoCase ///////////////////////////////////////////////////////
// Case-insensitive version of FindCommand.
pfConsoleCmd *pfConsoleCmdGroup::FindCommandNoCase( char *name, UInt8 flags, pfConsoleCmd *start )
{
pfConsoleCmd *cmd;
hsAssert( name != nil, "nil name passed to FindCommandNoCase()" );
/// Only search locally
if( start == nil )
start = fCommands;
else
start = start->GetNext();
if( flags & kFindPartial )
{
for( cmd = start; cmd != nil; cmd = cmd->GetNext() )
{
if( _strnicmp( cmd->GetName(), name, strlen( name ) ) == 0 )
return cmd;
}
}
else
{
for( cmd = start; cmd != nil; cmd = cmd->GetNext() )
{
if( stricmp( cmd->GetName(), name ) == 0 )
return cmd;
}
}
return nil;
}
//// FindSubGroupNoCase //////////////////////////////////////////////////////
pfConsoleCmdGroup *pfConsoleCmdGroup::FindSubGroupNoCase( char *name, UInt8 flags, pfConsoleCmdGroup *start )
{
pfConsoleCmdGroup *group;
hsAssert( name != nil, "nil name passed to FindSubGroupNoCase()" );
/// Only search locally
if( start == nil )
start = fSubGroups;
else
start = start->GetNext();
if( flags & kFindPartial )
{
for( group = start; group != nil; group = group->GetNext() )
{
if( _strnicmp( group->GetName(), name, strlen( name ) ) == 0 )
return group;
}
}
else
{
for( group = start; group != nil; group = group->GetNext() )
{
if( stricmp( group->GetName(), name ) == 0 )
return group;
}
}
return nil;
}
//// Link & Unlink ///////////////////////////////////////////////////////////
void pfConsoleCmdGroup::Link( pfConsoleCmdGroup **prevPtr )
{
hsAssert( fNext == nil && fPrevPtr == nil, "Trying to link console group that's already linked!" );
fNext = *prevPtr;
if( *prevPtr )
(*prevPtr)->fPrevPtr = &fNext;
fPrevPtr = prevPtr;
*fPrevPtr = this;
}
void pfConsoleCmdGroup::Unlink( void )
{
hsAssert( fNext != nil || fPrevPtr != nil, "Trying to unlink console group that isn't linked!" );
if( fNext )
fNext->fPrevPtr = fPrevPtr;
*fPrevPtr = fNext;
}
int pfConsoleCmdGroup::IterateCommands(pfConsoleCmdIterator* t, int depth)
{
pfConsoleCmd *cmd;
cmd = this->GetFirstCommand();
while(cmd)
{
t->ProcessCmd(cmd,depth);
cmd = cmd->GetNext();
}
pfConsoleCmdGroup *grp;
grp = this->GetFirstSubGroup();
while(grp)
{
if(t->ProcessGroup(grp, depth))
grp->IterateCommands(t, depth+1);
grp = grp->GetNext();
}
return 0;
}
//////////////////////////////////////////////////////////////////////////////
//// pfConsoleCmd Functions //////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
char pfConsoleCmd::fSigTypes[ kNumTypes ][ 8 ] = { "int", "float", "bool", "string", "char", "void", "..." };
pfConsoleCmd::pfConsoleCmd( char *group, char *name, char *paramList, char *help,
pfConsoleCmdPtr func, hsBool localOnly )
{
fNext = nil;
fPrevPtr = nil;
fFunction = func;
fLocalOnly = localOnly;
hsStrncpy( fName, name, sizeof( fName ) );
fHelpString = help;
ICreateSignature( paramList );
Register( group, name );
}
pfConsoleCmd::~pfConsoleCmd()
{
int i;
for( i = 0; i < fSigLabels.GetCount(); i++ )
{
if( fSigLabels[ i ] != nil )
delete [] fSigLabels[ i ];
}
Unregister();
fSignature.Reset();
fSigLabels.Reset();
}
//// ICreateSignature ////////////////////////////////////////////////////////
// Creates the signature and sig labels based on the given string.
void pfConsoleCmd::ICreateSignature( char *paramList )
{
static char seps[] = " :-";
char params[ 256 ];
char *ptr, *nextPtr, *tok, *tok2;
int i;
/// Simple check
if( paramList == nil )
{
fSignature.Push( kAny );
fSigLabels.Push( (char *)nil );
return;
}
/// So we can do stuff to it
hsAssert( strlen( paramList ) < sizeof( params ), "Make the (#*$& params string larger!" );
hsStrcpy( params, paramList );
fSignature.Empty();
fSigLabels.Empty();
/// Loop through all the types given in the list
ptr = params;
do
{
/// Find break
nextPtr = strchr( ptr, ',' );
if( nextPtr != nil )
{
*nextPtr = 0;
nextPtr++;
}
/// Do this param
tok = strtok( ptr, seps );
if( tok == nil && ptr == params )
break;
hsAssert( tok != nil, "Bad parameter list for console command!" );
tok2 = strtok( nil, seps );
if( tok2 != nil )
{
// Type and label: assume label second
fSigLabels.Push( hsStrcpy( tok2 ) );
}
else
fSigLabels.Push( (char *)nil );
// Find type
for( i = 0; i < kNumTypes; i++ )
{
if( strcmp( fSigTypes[ i ], tok ) == 0 )
{
fSignature.Push( (UInt8)i );
break;
}
}
hsAssert( i < kNumTypes, "Bad parameter type in console command parameter list!" );
} while( ( ptr = nextPtr ) != nil );
}
//// Register ////////////////////////////////////////////////////////////////
// Finds the group this command should be in and registers it with that
// group.
void pfConsoleCmd::Register( char *group, char *name )
{
pfConsoleCmdGroup *g;
if( group == nil || group[ 0 ] == 0 )
{
g = pfConsoleCmdGroup::GetBaseGroup();
g->AddCommand( this );
}
else
{
g = pfConsoleCmdGroup::FindSubGroupRecurse( group );
hsAssert( g != nil, "Trying to register command under nonexistant group!" );
g->AddCommand( this );
}
fParentGroup = g;
}
//// Unregister //////////////////////////////////////////////////////////////
void pfConsoleCmd::Unregister( void )
{
Unlink();
pfConsoleCmdGroup::DecBaseCmdGroupRef();
}
//// Execute /////////////////////////////////////////////////////////////////
// Run da thing!
void pfConsoleCmd::Execute( Int32 numParams, pfConsoleCmdParam *params, void (*PrintFn)( const char * ) )
{
fFunction( numParams, params, PrintFn );
}
//// Link & Unlink ///////////////////////////////////////////////////////////
void pfConsoleCmd::Link( pfConsoleCmd **prevPtr )
{
hsAssert( fNext == nil && fPrevPtr == nil, "Trying to link console command that's already linked!" );
fNext = *prevPtr;
if( *prevPtr )
(*prevPtr)->fPrevPtr = &fNext;
fPrevPtr = prevPtr;
*fPrevPtr = this;
}
void pfConsoleCmd::Unlink( void )
{
hsAssert( fNext != nil || fPrevPtr != nil, "Trying to unlink console command that isn't linked!" );
if( fNext )
fNext->fPrevPtr = fPrevPtr;
*fPrevPtr = fNext;
}
//// GetSigEntry /////////////////////////////////////////////////////////////
UInt8 pfConsoleCmd::GetSigEntry( UInt8 i )
{
if( fSignature.GetCount() == 0 )
return kNone;
if( i < fSignature.GetCount() )
{
if( fSignature[ i ] == kEtc )
return kAny;
return fSignature[ i ];
}
if( fSignature[ fSignature.GetCount() - 1 ] == kEtc )
return kAny;
return kNone;
}
//// GetSignature ////////////////////////////////////////////////////////////
// Gets the signature of the command as a string. Format is:
// name [ type param [, type param ... ] ]
// WARNING: uses a static buffer, so don't rely on the contents if you call
// it more than once! (You shouldn't need to, though)
const char *pfConsoleCmd::GetSignature( void )
{
static char string[ 256 ];
int i;
char pStr[ 128 ];
strcpy( string, fName );
for( i = 0; i < fSignature.GetCount(); i++ )
{
if( fSigLabels[ i ] == nil )
sprintf( pStr, "%s", fSigTypes[ fSignature[ i ] ] );
else
sprintf( pStr, "%s %s", fSigTypes[ fSignature[ i ] ], fSigLabels[ i ] );
hsAssert( strlen( string ) + strlen( pStr ) + 2 < sizeof( string ), "Not enough room for signature string" );
strcat( string, ( i > 0 ) ? ", " : " " );
strcat( string, pStr );
}
return string;
}
//////////////////////////////////////////////////////////////////////////////
//// pfConsoleCmdParam Functions /////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//// Conversion Functions ////////////////////////////////////////////////////
const int & pfConsoleCmdParam::IToInt( void ) const
{
hsAssert( fType == kInt || fType == kAny, "Trying to use a non-int parameter as an int!" );
static int i;
if( fType == kAny )
{
hsAssert( fValue.s != nil, "Weird parameter during conversion" );
i = atoi( fValue.s );
return i;
}
return fValue.i;
}
const float & pfConsoleCmdParam::IToFloat( void ) const
{
hsAssert( fType == kFloat || fType == kAny, "Trying to use a non-float parameter as a float!" );
static float f;
if( fType == kAny )
{
hsAssert( fValue.s != nil, "Weird parameter during conversion" );
f = (float)atof( fValue.s );
return f;
}
return fValue.f;
}
const bool & pfConsoleCmdParam::IToBool( void ) const
{
hsAssert( fType == kBool || fType == kAny, "Trying to use a non-bool parameter as a bool!" );
static bool b;
if( fType == kAny )
{
hsAssert( fValue.s != nil, "Weird parameter during conversion" );
if( atoi( fValue.s ) > 0 || stricmp( fValue.s, "true" ) == 0 )
b = true;
else
b = false;
return b;
}
return fValue.b;
}
const pfConsoleCmdParam::CharPtr & pfConsoleCmdParam::IToString( void ) const
{
hsAssert( fType == kString || fType == kAny, "Trying to use a non-string parameter as a string!" );
return fValue.s;
}
const char & pfConsoleCmdParam::IToChar( void ) const
{
hsAssert( fType == kChar || fType == kAny, "Trying to use a non-char parameter as a char!" );
static char c;
if( fType == kAny )
{
hsAssert( fValue.s != nil, "Weird parameter during conversion" );
c = fValue.s[ 0 ];
return c;
}
return fValue.c;
}

View File

@ -0,0 +1,272 @@
/*==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==*/
//////////////////////////////////////////////////////////////////////////////
// //
// pfConsoleCmd Header //
// //
//////////////////////////////////////////////////////////////////////////////
#ifndef _pfConsoleCmd_h
#define _pfConsoleCmd_h
#include "hsTypes.h"
#include "hsBiExpander.h"
//// pfConsoleCmdGroup Class Definition //////////////////////////////////////
class pfConsoleCmd;
class pfConsoleCmdIterator;
class pfConsoleCmdGroup
{
protected:
static pfConsoleCmdGroup *fBaseCmdGroup;
static UInt32 fBaseCmdGroupRef;
char fName[ 128 ];
pfConsoleCmdGroup *fNext;
pfConsoleCmdGroup **fPrevPtr;
pfConsoleCmdGroup *fSubGroups;
pfConsoleCmd *fCommands;
pfConsoleCmdGroup *fParentGroup;
public:
enum FindFlags {
kFindPartial = 0x01
};
pfConsoleCmdGroup( char *name, char *parent );
~pfConsoleCmdGroup();
void AddCommand( pfConsoleCmd *cmd );
void AddSubGroup( pfConsoleCmdGroup *group );
void Link( pfConsoleCmdGroup **prevPtr );
void Unlink( void );
pfConsoleCmdGroup *GetNext( void ) { return fNext; }
char *GetName( void ) { return fName; }
pfConsoleCmdGroup *GetParent( void ) { return fParentGroup; }
static pfConsoleCmdGroup *GetBaseGroup( void );
pfConsoleCmd *FindCommand( char *name );
pfConsoleCmd *FindCommandNoCase( char *name, UInt8 flags = 0, pfConsoleCmd *start = nil );
pfConsoleCmd *FindNestedPartialCommand( char *name, UInt32 *counter );
pfConsoleCmdGroup *FindSubGroup( char *name );
pfConsoleCmdGroup *FindSubGroupNoCase( char *name, UInt8 flags = 0, pfConsoleCmdGroup *start = nil );
pfConsoleCmd *GetFirstCommand( void ) { return fCommands; }
pfConsoleCmdGroup *GetFirstSubGroup( void ) { return fSubGroups; }
int IterateCommands(pfConsoleCmdIterator*, int depth=0);
static pfConsoleCmdGroup *FindSubGroupRecurse( const char *name );
static void DecBaseCmdGroupRef( void );
static void Dummy( void );
static void DummyJunior( void );
static void DummyNet( void );
static void DummyAvatar( void );
static void DummyCCR( void );
};
//// pfConsoleCmdParam Class Definition //////////////////////////////////////
class pfConsoleCmdParam
{
protected:
UInt8 fType;
typedef char *CharPtr;
union
{
int i;
float f;
bool b;
CharPtr s;
char c;
} fValue;
const int &IToInt( void ) const;
const float &IToFloat( void ) const;
const bool &IToBool( void ) const;
const CharPtr &IToString( void ) const;
const char &IToChar( void ) const;
public:
enum Types
{
kInt = 0,
kFloat,
kBool,
kString,
kChar,
kAny,
kNone = 0xff
};
operator int() const { return IToInt(); }
operator float() const { return IToFloat(); }
operator bool() const { return IToBool(); }
operator const CharPtr() const { return IToString(); }
operator char() const { return IToChar(); }
UInt8 GetType( void ) { return fType; }
void SetInt( int i ) { fValue.i = i; fType = kInt; }
void SetFloat( float f ) { fValue.f = f; fType = kFloat; }
void SetBool( bool b ) { fValue.b = b; fType = kBool; }
void SetString( CharPtr s ) { fValue.s = s; fType = kString; }
void SetChar( char c ) { fValue.c = c; fType = kChar; }
void SetAny( CharPtr s ) { fValue.s = s; fType = kAny; }
void SetNone( void ) { fType = kNone; }
};
//// pfConsoleCmd Class Definition ///////////////////////////////////////////
typedef void (*pfConsoleCmdPtr)( Int32 numParams, pfConsoleCmdParam *params, void (*PrintString)( const char * ) );
class pfConsoleCmd
{
protected:
char fName[ 128 ];
char *fHelpString;
pfConsoleCmdPtr fFunction;
hsBool fLocalOnly;
pfConsoleCmd *fNext;
pfConsoleCmd **fPrevPtr;
pfConsoleCmdGroup *fParentGroup;
hsExpander<UInt8> fSignature;
hsExpander<char *> fSigLabels;
void ICreateSignature( char *paramList );
public:
enum ParamTypes
{
kInt = 0,
kFloat,
kBool,
kString,
kChar,
kAny,
kEtc,
kNumTypes,
kNone = 0xff
};
static char fSigTypes[ kNumTypes ][ 8 ];
pfConsoleCmd( char *group, char *name, char *paramList, char *help, pfConsoleCmdPtr func, hsBool localOnly = false );
~pfConsoleCmd();
void Register( char *group, char *name );
void Unregister();
void Execute( Int32 numParams, pfConsoleCmdParam *params, void (*PrintFn)( const char * ) = nil );
void Link( pfConsoleCmd **prevPtr );
void Unlink( void );
pfConsoleCmd *GetNext( void ) { return fNext; }
char *GetName( void ) { return fName; }
char *GetHelp( void ) { return fHelpString; }
const char *GetSignature( void );
pfConsoleCmdGroup *GetParent( void ) { return fParentGroup; }
UInt8 GetSigEntry( UInt8 i );
};
class pfConsoleCmdIterator
{
public:
virtual void ProcessCmd(pfConsoleCmd*, int ) {}
virtual bool ProcessGroup(pfConsoleCmdGroup *, int) {return true;}
};
//// pfConsoleCmd Creation Macro /////////////////////////////////////////////
//
// This expands into 3 things:
// - A prototype for the function.
// - A declaration of a pfConsoleCmd object, which takes in that function
// as a parameter
// - The start of the function itself, so that the {} after the macro
// define the body of that function.
//
// PF_LOCAL_CONSOLE_CMD is identical, only it passes true for the localOnly flag.
// This isn't used currently and is here only for legacy.
// PF_CONSOLE_BASE_CMD doesn't belong to a group; it creates a global console function.
#define PF_CONSOLE_BASE_CMD( name, p, help ) \
void pfConsoleCmd_##name##_proc( Int32 numParams, pfConsoleCmdParam *params, void (*PrintString)( const char * ) ); \
pfConsoleCmd conCmd_##name( nil, #name, p, help, pfConsoleCmd_##name##_proc ); \
void pfConsoleCmd_##name##_proc( Int32 numParams, pfConsoleCmdParam *params, void (*PrintString)( const char * ) )
#define PF_CONSOLE_CMD( grp, name, p, help ) \
void pfConsoleCmd_##grp##_##name##_proc( Int32 numParams, pfConsoleCmdParam *params, void (*PrintString)( const char * ) ); \
pfConsoleCmd conCmd_##grp##_##name( #grp, #name, p, help, pfConsoleCmd_##grp##_##name##_proc ); \
void pfConsoleCmd_##grp##_##name##_proc( Int32 numParams, pfConsoleCmdParam *params, void (*PrintString)( const char * ) )
#define PF_LOCAL_CONSOLE_CMD( grp, name, p, help ) \
void pfConsoleCmd_##grp##_##name##_proc( Int32 numParams, pfConsoleCmdParam *params, void (*PrintString)( const char * ) ); \
pfConsoleCmd conCmd_##grp##_##name( #grp, #name, p, help, pfConsoleCmd_##grp##_##name##_proc, true ); \
void pfConsoleCmd_##grp##_##name##_proc( Int32 numParams, pfConsoleCmdParam *params, void (*PrintString)( const char * ) )
//// pfConsoleCmdGroup Creation Macro ////////////////////////////////////////
#define PF_CONSOLE_GROUP( name ) \
pfConsoleCmdGroup conGroup_##name( #name, nil );
#define PF_CONSOLE_SUBGROUP( parent, name ) \
pfConsoleCmdGroup conGroup_##parent##_##name( #name, #parent );
#endif //_pfConsoleCmd_h

View File

@ -0,0 +1,276 @@
/*==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==*/
//////////////////////////////////////////////////////////////////////////////
// //
// pfConsoleContext //
// //
//////////////////////////////////////////////////////////////////////////////
#include "hsTypes.h"
#include "pfConsoleContext.h"
//// Static Root Context /////////////////////////////////////////////////////
pfConsoleContext pfConsoleContext::fRootContext( "global" );
pfConsoleContext &pfConsoleContext::GetRootContext( void )
{
return fRootContext;
}
//// Constructor/Destructor //////////////////////////////////////////////////
pfConsoleContext::pfConsoleContext( const char *name )
{
fName = ( name != nil ) ? hsStrcpy( name ) : nil;
fAddWhenNotFound = true;
}
pfConsoleContext::~pfConsoleContext()
{
Clear();
delete [] fName;
}
//// Clear ///////////////////////////////////////////////////////////////////
void pfConsoleContext::Clear( void )
{
Int32 idx;
for( idx = fVarValues.GetCount() - 1; idx >= 0; idx-- )
RemoveVar( idx );
}
//// Getters /////////////////////////////////////////////////////////////////
UInt32 pfConsoleContext::GetNumVars( void ) const
{
hsAssert( fVarValues.GetCount() == fVarNames.GetCount(), "Mismatch in console var context arrays" );
return fVarValues.GetCount();
}
const char *pfConsoleContext::GetVarName( UInt32 idx ) const
{
hsAssert( fVarValues.GetCount() == fVarNames.GetCount(), "Mismatch in console var context arrays" );
if( idx >= fVarNames.GetCount() )
{
hsAssert( false, "GetVarName() index out of range for console context" );
return nil;
}
return fVarNames[ idx ];
}
pfConsoleCmdParam &pfConsoleContext::GetVarValue( UInt32 idx ) const
{
hsAssert( fVarValues.GetCount() == fVarNames.GetCount(), "Mismatch in console var context arrays" );
hsAssert( idx < fVarValues.GetCount(), "GetVarValue() index out of range for console context" );
return fVarValues[ idx ];
}
//// FindVar /////////////////////////////////////////////////////////////////
Int32 pfConsoleContext::FindVar( const char *name ) const
{
UInt32 idx;
hsAssert( fVarValues.GetCount() == fVarNames.GetCount(), "Mismatch in console var context arrays" );
for( idx = 0; idx < fVarNames.GetCount(); idx++ )
{
if( stricmp( name, fVarNames[ idx ] ) == 0 )
{
return (Int32)idx;
}
}
return -1;
}
//// RemoveVar ///////////////////////////////////////////////////////////////
void pfConsoleContext::RemoveVar( UInt32 idx )
{
hsAssert( fVarValues.GetCount() == fVarNames.GetCount(), "Mismatch in console var context arrays" );
if( idx >= fVarValues.GetCount() )
{
hsAssert( false, "RemoveVar() index out of range for console context" );
return;
}
delete [] fVarNames[ idx ];
if( fVarValues[ idx ].GetType() == pfConsoleCmdParam::kString )
// Necessary because the params won't delete the data themselves
delete [] ( (char *)fVarValues[ idx ] );
fVarNames.Remove( idx );
fVarValues.Remove( idx );
}
//// AddVar Variants /////////////////////////////////////////////////////////
void pfConsoleContext::IAddVar( const char *name, const pfConsoleCmdParam &value )
{
fVarNames.Append( hsStrcpy( name ) );
fVarValues.Append( value );
// Remember, params won't know any better, since by default they don't own a copy of their string
UInt32 idx = fVarValues.GetCount() - 1;
if( fVarValues[ idx ].GetType() == pfConsoleCmdParam::kString )
fVarValues[ idx ].SetString( hsStrcpy( fVarValues[ idx ] ) );
}
void pfConsoleContext::AddVar( const char *name, const pfConsoleCmdParam &value )
{
Int32 idx = FindVar( name );
if( idx != -1 )
{
hsAssert( false, "AddVar() failed because variable already in console context" );
return;
}
IAddVar( name, value );
}
void pfConsoleContext::AddVar( const char *name, int value )
{
pfConsoleCmdParam param;
param.SetInt( value );
AddVar( name, param );
}
void pfConsoleContext::AddVar( const char *name, float value )
{
pfConsoleCmdParam param;
param.SetFloat( value );
AddVar( name, param );
}
void pfConsoleContext::AddVar( const char *name, const char *value )
{
pfConsoleCmdParam param;
param.SetString( (char *)value ); // It's ok, we'll be copying it soon 'nuf
AddVar( name, param );
}
void pfConsoleContext::AddVar( const char *name, char value )
{
pfConsoleCmdParam param;
param.SetChar( value );
AddVar( name, param );
}
void pfConsoleContext::AddVar( const char *name, bool value )
{
pfConsoleCmdParam param;
param.SetBool( value );
AddVar( name, param );
}
//// SetVar Variants /////////////////////////////////////////////////////////
hsBool pfConsoleContext::SetVar( UInt32 idx, const pfConsoleCmdParam &value )
{
hsAssert( fVarValues.GetCount() == fVarNames.GetCount(), "Mismatch in console var context arrays" );
if( idx >= fVarValues.GetCount() )
{
hsAssert( false, "SetVar() index out of range for console context" );
return false;
}
if( fVarValues[ idx ].GetType() == pfConsoleCmdParam::kString )
{
// Remember, params won't know any better, since by default they don't own a copy of their string
delete [] ( (char *)fVarValues[ idx ] );
}
fVarValues[ idx ] = value;
if( fVarValues[ idx ].GetType() == pfConsoleCmdParam::kString )
fVarValues[ idx ].SetString( hsStrcpy( fVarValues[ idx ] ) );
return true;
}
hsBool pfConsoleContext::SetVar( const char *name, const pfConsoleCmdParam &value )
{
Int32 idx = FindVar( name );
if( idx == -1 )
{
if( fAddWhenNotFound )
{
// Don't panic, just add
IAddVar( name, value );
return true;
}
return false;
}
return SetVar( idx, value );
}
hsBool pfConsoleContext::SetVar( const char *name, int value )
{
pfConsoleCmdParam param;
param.SetInt( value );
return SetVar( name, param );
}
hsBool pfConsoleContext::SetVar( const char *name, float value )
{
pfConsoleCmdParam param;
param.SetFloat( value );
return SetVar( name, param );
}
hsBool pfConsoleContext::SetVar( const char *name, const char *value )
{
pfConsoleCmdParam param;
param.SetString( (char *)value ); // Don't worry, we'll be copying it soon 'nuf
return SetVar( name, param );
}
hsBool pfConsoleContext::SetVar( const char *name, char value )
{
pfConsoleCmdParam param;
param.SetChar( value );
return SetVar( name, param );
}
hsBool pfConsoleContext::SetVar( const char *name, bool value )
{
pfConsoleCmdParam param;
param.SetBool( value );
return SetVar( name, param );
}

View File

@ -0,0 +1,95 @@
/*==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==*/
//////////////////////////////////////////////////////////////////////////////
// //
// pfConsoleContext Header //
// //
//////////////////////////////////////////////////////////////////////////////
#ifndef _pfConsoleContext_h
#define _pfConsoleContext_h
#include "hsTypes.h"
#include "pfConsoleCmd.h"
//// Class Definition ////////////////////////////////////////////////////////
class pfConsoleContext
{
protected:
hsBool fAddWhenNotFound; // Controls whether we add variables on Set() calls if they're not found
char *fName;
hsTArray<char *> fVarNames;
hsTArray<pfConsoleCmdParam> fVarValues;
void IAddVar( const char *name, const pfConsoleCmdParam &value );
static pfConsoleContext fRootContext;
public:
pfConsoleContext( const char *name );
virtual ~pfConsoleContext();
void Clear( void );
UInt32 GetNumVars( void ) const;
const char *GetVarName( UInt32 idx ) const;
pfConsoleCmdParam &GetVarValue( UInt32 idx ) const;
Int32 FindVar( const char *name ) const;
void RemoveVar( UInt32 idx );
void AddVar( const char *name, const pfConsoleCmdParam &value );
void AddVar( const char *name, int value );
void AddVar( const char *name, float value );
void AddVar( const char *name, const char *value );
void AddVar( const char *name, char value );
void AddVar( const char *name, bool value );
hsBool SetVar( UInt32 idx, const pfConsoleCmdParam &value );
hsBool SetVar( const char *name, const pfConsoleCmdParam &value );
hsBool SetVar( const char *name, int value );
hsBool SetVar( const char *name, float value );
hsBool SetVar( const char *name, const char *value );
hsBool SetVar( const char *name, char value );
hsBool SetVar( const char *name, bool value );
// Decide whether Sets() on nonexistant variables will fail or add a new variable
void SetAddWhenNotFound( hsBool f ) { fAddWhenNotFound = f; }
hsBool GetAddWhenNotFound( void ) const { return fAddWhenNotFound; }
static pfConsoleContext &GetRootContext( void );
};
#endif //_pfConsoleContext_h

View File

@ -0,0 +1,36 @@
/*==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 pfConsoleCreatable_inc
#define pfConsoleCreatable_inc
#include "../pnFactory/plCreator.h"
#include "pfConsole.h"
REGISTER_CREATABLE( pfConsole );
#endif // pfConsoleCreatable_inc

View File

@ -0,0 +1,149 @@
/*==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==*/
//////////////////////////////////////////////////////////////////////////////
// //
// pfConsoleDirSrc Functions //
// //
//////////////////////////////////////////////////////////////////////////////
#include "pfConsoleDirSrc.h"
#include "hsExceptions.h"
#ifdef HS_BUILD_FOR_WIN32
#define WIN32_EXTRA_LEAN
#define WIN32_LEAN_AND_MEAN
#ifndef _WINDOWS_H_ // redundant include guard to minimize compile times
#define _WINDOWS_H_
#include <windows.h>
#endif // _WINDOWS_H_
#include <winbase.h>
#include <sstream>
//// ParseDirectory //////////////////////////////////////////////////////////
hsBool pfConsoleDirSrc::ParseDirectory(const std::string& path, const std::string& mask /* = "*.*" */)
{
wchar* wPath = hsStringToWString(path.c_str());
wchar* wMask = hsStringToWString(mask.c_str());
hsBool ret = ParseDirectory(wPath, wMask);
delete [] wPath;
delete [] wMask;
return ret;
}
hsBool pfConsoleDirSrc::ParseDirectory(const std::wstring& path, const std::wstring& mask /* = L"*.*" */)
{
std::wstringstream search;
std::wstring file;
WIN32_FIND_DATAW findInfo;
HANDLE handle;
hsAssert( fEngine != nil, "Cannot do a dir execute without an engine!" );
search << path << L"\\" << mask;
handle = FindFirstFileW(search.str().c_str(), &findInfo);
if (handle == INVALID_HANDLE_VALUE)
return false;
do
{
if (!( findInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
{
std::wstringstream fileAndPath;
fileAndPath << path << L"\\" << findInfo.cFileName;
if (AlreadyProcessedFile(path, findInfo.cFileName))
continue;
AddProcessedFile(path, findInfo.cFileName);
if (!fEngine->ExecuteFile(fileAndPath.str().c_str()))
{
// Change the following line once we have a better way of reporting
// errors in the parsing
std::wstringstream error;
std::wstringstream caption;
wchar* errorMsg = hsStringToWString(fEngine->GetErrorMsg());
wchar* errorLine = hsStringToWString(fEngine->GetLastErrorLine());
caption << L"Error parsing " << findInfo.cFileName;
error << errorMsg << L":\n\nCommand: '" << errorLine << L"'\n\nPress OK to continue parsing files.";
hsMessageBox(error.str().c_str(), caption.str().c_str(), hsMessageBoxNormal);
delete [] errorMsg;
delete [] errorLine;
FindClose(handle);
SetCheckProcessedFiles(true);
return false;
}
}
} while (FindNextFileW(handle, &findInfo) != 0);
FindClose(handle);
SetCheckProcessedFiles(true);
return true;
}
#else
#error This needs to be implemented for this platform!!!!
#endif
void pfConsoleDirSrc::ResetProcessedFiles()
{
int i;
for(i=0;i<fProcessedFiles.size(); i++)
delete fProcessedFiles[i];
fProcessedFiles.clear();
}
//
// note: this n^2 linear search should be replaced with something
// faster if we have lots of init files and turn on the checkProcessing option.
//
hsBool pfConsoleDirSrc::AlreadyProcessedFile(const std::wstring& path, const std::wstring& file)
{
if (fCheckProcessedFiles)
{
int i;
for(i=0; i<fProcessedFiles.size(); i++)
{
if (file == fProcessedFiles[i]->fFile && path == fProcessedFiles[i]->fPath)
return true;
}
}
return false;
}
void pfConsoleDirSrc::AddProcessedFile(const std::wstring& path, const std::wstring& file)
{
fProcessedFiles.push_back(TRACKED_NEW FileName(path, file));
}

View File

@ -0,0 +1,89 @@
/*==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==*/
//////////////////////////////////////////////////////////////////////////////
// //
// pfConsoleDirSrc Header //
// //
//// Description /////////////////////////////////////////////////////////////
// //
// Simple wrapper for parsing an entire directory of files and executing //
// each one through the pfConsoleEngine object given. //
// I.E. the source for the console commmands is a directory of files, //
// hence it's a Console Directory Source, or ConsoleDirSrc. :) //
// //
//////////////////////////////////////////////////////////////////////////////
#ifndef _pfConsoleDirSrc_h
#define _pfConsoleDirSrc_h
#include "hsTypes.h"
#include "hsStlUtils.h"
#include "pfConsoleEngine.h"
//// pfConsoleDirSrc Class Definition ////////////////////////////////////////
class pfConsoleDirSrc
{
protected:
pfConsoleEngine *fEngine;
struct FileName
{
std::wstring fPath;
std::wstring fFile;
FileName() : fPath(L""), fFile(L"") {}
FileName(const std::wstring& p, const std::wstring& f) : fPath(p), fFile(f) {}
};
std::vector<FileName*> fProcessedFiles; // list of init files we've already executed
hsBool fCheckProcessedFiles; // set to check and skip files init files we've already executed
public:
pfConsoleDirSrc(pfConsoleEngine *engine) : fCheckProcessedFiles(false) { fEngine = engine; }
pfConsoleDirSrc(pfConsoleEngine *engine, const std::string& path, const std::string& mask = "*.ini") :
fCheckProcessedFiles(false)
{
fEngine = engine;
ParseDirectory(path, mask);
}
pfConsoleDirSrc(pfConsoleEngine *engine, const std::wstring& path, const std::wstring& mask = L"*.ini") :
fCheckProcessedFiles(false)
{
fEngine = engine;
ParseDirectory(path, mask);
}
~pfConsoleDirSrc() { ResetProcessedFiles(); }
// Steps through the given directory and executes all files with the console engine
hsBool ParseDirectory(const std::string& path, const std::string& mask = "*.*");
hsBool ParseDirectory(const std::wstring& path, const std::wstring& mask = L"*.*");
void ResetProcessedFiles();
hsBool AlreadyProcessedFile(const std::wstring& path, const std::wstring& file);
void AddProcessedFile(const std::wstring& path, const std::wstring& file);
void SetCheckProcessedFiles(hsBool c) { fCheckProcessedFiles=c; }
};
#endif //_pfConsoleDirSrc_h

View File

@ -0,0 +1,579 @@
/*==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==*/
//////////////////////////////////////////////////////////////////////////////
// //
// pfConsoleEngine Functions //
// //
//////////////////////////////////////////////////////////////////////////////
#include "pfConsoleEngine.h"
#include "pfConsoleCmd.h"
#include "pfConsoleContext.h"
#include "../plFile/plEncryptedStream.h"
const Int32 pfConsoleEngine::fMaxNumParams = 16;
const char pfConsoleEngine::fTokenSeparators[] = " =\r\n\t,";
const char pfConsoleEngine::fTokenGrpSeps[] = " =\r\n._\t,";
//// Constructor & Destructor ////////////////////////////////////////////////
pfConsoleEngine::pfConsoleEngine()
{
}
pfConsoleEngine::~pfConsoleEngine()
{
}
//// PrintCmdHelp ////////////////////////////////////////////////////////////
hsBool pfConsoleEngine::PrintCmdHelp( char *name, void (*PrintFn)( const char * ) )
{
pfConsoleCmd *cmd;
pfConsoleCmdGroup *group, *subGrp;
char *ptr;
static char string[ 512 ];
static char tempString[ 512 ];
UInt32 i;
/// Scan for subgroups. This can be an empty loop
group = pfConsoleCmdGroup::GetBaseGroup();
ptr = strtok( name, fTokenGrpSeps );
while( ptr != nil )
{
// Take this token and check to see if it's a group
if( ( subGrp = group->FindSubGroupNoCase( ptr ) ) != nil )
group = subGrp;
else
break;
ptr = strtok( nil, fTokenGrpSeps );
}
if( ptr == nil )
{
if( group == nil )
{
ISetErrorMsg( "Invalid command syntax" );
return false;
}
// Print help for this group
if( group == pfConsoleCmdGroup::GetBaseGroup() )
strcpy( string, "Base commands and groups:" );
else
sprintf( string, "Group %s:", group->GetName() );
PrintFn( string );
PrintFn( " Subgroups:" );
for( subGrp = group->GetFirstSubGroup(); subGrp != nil; subGrp = subGrp->GetNext() )
{
sprintf( string, " %s", subGrp->GetName() );
PrintFn( string );
}
PrintFn( " Commands:" );
for( cmd = group->GetFirstCommand(); cmd != nil; cmd = cmd->GetNext() )
{
for( ptr = cmd->GetHelp(), i = 0; ptr[ i ] != 0 && ptr[ i ] != '\n'; i++ )
tempString[ i ] = ptr[ i ];
tempString[ i ] = 0;
sprintf( string, " %s: %s", cmd->GetName(), tempString );
PrintFn( string );
}
return true;
}
/// OK, so what we found wasn't a group. Which means we need a command...
cmd = group->FindCommandNoCase( ptr );
if( cmd == nil )
{
ISetErrorMsg( "Invalid syntax: command not found" );
return false;
}
/// That's it!
sprintf( string, "\nHelp for the command %s:", cmd->GetName() );
PrintFn( string );
sprintf( string, "\\i%s", cmd->GetHelp() );
PrintFn( string );
sprintf( string, "\\iUsage: %s", cmd->GetSignature() );
PrintFn( string );
return true;
}
//// GetCmdSignature /////////////////////////////////////////////////////////
const char *pfConsoleEngine::GetCmdSignature( char *name )
{
pfConsoleCmd *cmd;
pfConsoleCmdGroup *group, *subGrp;
char *ptr;
static char string[ 512 ];
/// Scan for subgroups. This can be an empty loop
group = pfConsoleCmdGroup::GetBaseGroup();
ptr = strtok( name, fTokenGrpSeps );
while( ptr != nil )
{
// Take this token and check to see if it's a group
if( ( subGrp = group->FindSubGroupNoCase( ptr ) ) != nil )
group = subGrp;
else
break;
ptr = strtok( nil, fTokenGrpSeps );
}
if( ptr == nil )
{
ISetErrorMsg( "Invalid command syntax" );
return nil;
}
/// OK, so what we found wasn't a group. Which means we need a command...
cmd = group->FindCommandNoCase( ptr );
if( cmd == nil )
{
ISetErrorMsg( "Invalid syntax: command not found" );
return nil;
}
/// That's it!
return (char *)cmd->GetSignature();
}
//// Dummy Local Function ////////////////////////////////////////////////////
void DummyPrintFn( const char *line )
{
}
//// ExecuteFile /////////////////////////////////////////////////////////////
hsBool pfConsoleEngine::ExecuteFile( const char *fileName )
{
wchar* wFilename = hsStringToWString(fileName);
hsBool ret = ExecuteFile(wFilename);
delete [] wFilename;
return ret;
}
hsBool pfConsoleEngine::ExecuteFile( const wchar *fileName )
{
char string[ 512 ];
int line;
hsStream* stream = plEncryptedStream::OpenEncryptedFile(fileName);
if( !stream )
{
ISetErrorMsg( "Cannot open given file" );
// return false;
/// THIS IS BAD: because of the asserts we throw after this if we return false, a missing
/// file will throw an assert. This is all well and good except for the age-specific .fni files,
/// which aren't required to be there and rely on this functionality to test whether the file is
/// present. Once age-specific .fni's are gone, reinstate the return false here. -mcn
return true;
}
for( line = 1; stream->ReadLn( string, sizeof( string ) ); line++ )
{
strncpy( fLastErrorLine, string, sizeof( fLastErrorLine ) );
if( !RunCommand( string, DummyPrintFn ) )
{
sprintf( string, "Error in console file %s, command line %d: %s", fileName, line, fErrorMsg );
ISetErrorMsg( string );
stream->Close();
delete stream;
return false;
}
}
stream->Close();
delete stream;
fLastErrorLine[ 0 ] = 0;
return true;
}
//// RunCommand //////////////////////////////////////////////////////////////
// Updated 2.14.2001 mcn to support spaces, _ or . as group separators. This
// requires tokenizing the entire line and searching the tokens one by one,
// parsing them first as groups, then commands and then params.
hsBool pfConsoleEngine::RunCommand( char *line, void (*PrintFn)( const char * ) )
{
pfConsoleCmd *cmd;
pfConsoleCmdGroup *group, *subGrp;
Int32 numParams, i, numQuotedParams = 0;
pfConsoleCmdParam paramArray[ fMaxNumParams + 1 ];
char *ptr;
hsBool valid = true;
hsAssert( line != nil, "Bad parameter to RunCommand()" );
/// Loop #1: Scan for subgroups. This can be an empty loop
group = pfConsoleCmdGroup::GetBaseGroup();
ptr = strtok( line, fTokenGrpSeps );
while( ptr != nil )
{
// Take this token and check to see if it's a group
if( ( subGrp = group->FindSubGroupNoCase( ptr ) ) != nil )
group = subGrp;
else
break;
ptr = strtok( nil, fTokenGrpSeps );
}
if( ptr == nil )
{
ISetErrorMsg( "Invalid command syntax" );
return false;
}
/// OK, so what we found wasn't a group. Which means we need a command next
cmd = group->FindCommandNoCase( ptr );
if( cmd == nil )
{
ISetErrorMsg( "Invalid syntax: command not found" );
return false;
}
/// We have the group, we have the command from that group. So continue
/// tokenizing (with the new separators now, mind you) and turn them into
/// params
for( numParams = numQuotedParams = 0; numParams < fMaxNumParams
&& ( ptr = strtok( nil, fTokenSeparators ) ) != nil
&& valid; numParams++ )
{
if( ptr[ 0 ] == '\'' || ptr[ 0 ] == '"' )
{
// String parameter--keep getting tokens until we hit the other end
// Note: since params take pointers to strings, we have to have unique temp strings
// for each quoted param we parse. So we have a static array here to a) do so, b)
// avoid having to delete them afterwards, and thus c) reduce overhead.
static char tempStrings[ fMaxNumParams ][ 512 ];
char *tempStr = tempStrings[ numQuotedParams++ ], toSearch[ 2 ] = "'";
toSearch[ 0 ] = ptr[ 0 ];
if( strlen( ptr ) >= sizeof( tempStrings[ 0 ] ) ) // They're all the same, after all...
{
ISetErrorMsg( "Invalid syntax: quoted parameter too long" );
return false;
}
if( strlen( ptr ) > 1 && ptr[ strlen( ptr ) - 1 ] == toSearch[ 0 ] )
{
// Single word string
strcpy( tempStr, ptr + 1 );
tempStr[ strlen( tempStr ) - 1 ] = 0;
}
else
{
// Multiple word string
sprintf( tempStr, "%s ", ptr + 1 ); // Not perfect, but close
ptr = strtok( nil, toSearch );
if( ptr == nil )
{
ISetErrorMsg( "Invalid syntax: unterminated quoted parameter" );
return false;
}
if( strlen( ptr ) + strlen( tempStr ) >= sizeof( tempStrings[ 0 ] ) ) // They're all the same, after all...
{
ISetErrorMsg( "Invalid syntax: quoted parameter too long" );
return false;
}
strcat( tempStr, ptr );
}
valid = IConvertToParam( cmd->GetSigEntry( (UInt8)numParams ), tempStr, &paramArray[ numParams ] );
}
else
{
// Normal parameter
// Special case for context variables--if we're specifying one, we want to just grab
// the value of it and return that instead
valid = false;
if( ptr[ 0 ] == '$' )
{
pfConsoleContext &context = pfConsoleContext::GetRootContext();
// Potential variable, see if we can find it
Int32 idx = context.FindVar( ptr + 1 );
if( idx == -1 )
{
ISetErrorMsg( "Invalid console variable name" );
}
else
{
// Just copy. Note that this will copy string pointers, but so long as the variable in
// question doesn't change, we'll be OK...
paramArray[ numParams ] = context.GetVarValue( idx );
valid = true;
}
}
if( !valid )
valid = IConvertToParam( cmd->GetSigEntry( (UInt8)numParams ), ptr, &paramArray[ numParams ] );
}
}
for( i = numParams; i < fMaxNumParams + 1; i++ )
paramArray[ i ].SetNone();
if( !valid || ( cmd->GetSigEntry( (UInt8)numParams ) != pfConsoleCmd::kAny &&
cmd->GetSigEntry( (UInt8)numParams ) != pfConsoleCmd::kNone ) )
{
// Print help string and return
static char string[ 512 ];
ISetErrorMsg( "" ); // Printed on next line
PrintFn( "Invalid parameters to command" );
sprintf( string, "Usage: %s", cmd->GetSignature() );
PrintFn( string );
return false;
}
/// Execute it and return
cmd->Execute( numParams, paramArray, PrintFn );
return true;
}
//// IConvertToParam /////////////////////////////////////////////////////////
// Converts a null-terminated string representing a parameter to a
// pfConsoleCmdParam argument.
hsBool pfConsoleEngine::IConvertToParam( UInt8 type, char *string, pfConsoleCmdParam *param )
{
char *c, expChars[] = "dDeE+-.";
hsBool hasDecimal = false, hasLetters = false;
if( type == pfConsoleCmd::kNone )
return false;
for( c = string; *c != 0; c++ )
{
if( !isdigit( *c ) )
{
if( c == string && ( *c == '-' || *c == '+' ) )
{
// Do nothing--perfectly legal to have these at the beginning of an int
}
else if( strchr( expChars, *c ) != nil )
hasDecimal = true;
else
hasLetters = true;
}
}
if( type == pfConsoleCmd::kAny )
{
/// Want "any"
param->SetAny( string );
}
else if( type == pfConsoleCmd::kString )
{
/// Want just a string
param->SetString( string );
}
else if( type == pfConsoleCmd::kFloat )
{
if( hasLetters )
return false;
param->SetFloat( (float)atof( string ) );
}
else if( type == pfConsoleCmd::kInt )
{
if( hasLetters || hasDecimal )
return false;
param->SetInt( atoi( string ) );
}
else if( type == pfConsoleCmd::kBool )
{
if( stricmp( string, "true" ) == 0 || stricmp( string, "t" ) == 0 )
param->SetBool( true );
else if( stricmp( string, "false" ) == 0 || stricmp( string, "f" ) == 0 )
param->SetBool( false );
else if( atoi( string ) == 0 )
param->SetBool( false );
else
param->SetBool( true );
}
return true;
}
//// FindPartialCmd //////////////////////////////////////////////////////////
// Given a string which is the beginning of a console command, modifies the
// string to represent the best match of command (or group) for that string.
// WARNING: modifies the string passed to it.
hsBool pfConsoleEngine::FindPartialCmd( char *line, hsBool findAgain, hsBool preserveParams )
{
pfConsoleCmd *cmd = nil;
pfConsoleCmdGroup *group, *subGrp;
hsBool foundMore = false;
static char *ptr = nil, *insertLoc = nil;
static pfConsoleCmd *lastCmd = nil;
static pfConsoleCmdGroup *lastGroup = nil, *lastParentGroup = nil;
static char newStr[ 256 ];
/// Repeat search
if( !findAgain )
{
lastCmd = nil;
lastGroup = nil;
}
/// New search
if( strlen( line ) > sizeof( newStr ) )
return false;
newStr[ 0 ] = 0;
insertLoc = newStr;
/// Loop #1: Scan for subgroups. This can be an empty loop
lastParentGroup = group = pfConsoleCmdGroup::GetBaseGroup();
ptr = strtok( line, fTokenGrpSeps );
while( ptr != nil )
{
// Take this token and check to see if it's a group
if( ( subGrp = group->FindSubGroupNoCase( ptr, 0/*pfConsoleCmdGroup::kFindPartial*/
, /*lastGroup*/nil ) ) != nil )
{
lastParentGroup = group;
group = subGrp;
strcat( newStr, group->GetName() );
insertLoc += strlen( group->GetName() );
}
else
break;
ptr = strtok( nil, fTokenGrpSeps );
strcat( newStr, "." );
insertLoc++;
}
if( ptr != nil )
{
// Still got at least one token left. Try to match to either
// a partial group or a partial command
if( ( subGrp = group->FindSubGroupNoCase( ptr, pfConsoleCmdGroup::kFindPartial, lastGroup ) ) != nil )
{
lastParentGroup = group;
lastGroup = group = subGrp;
strcat( newStr, group->GetName() );
strcat( newStr, "." );
}
else
{
cmd = group->FindCommandNoCase( ptr, pfConsoleCmdGroup::kFindPartial, lastCmd );
if( cmd == nil )
return false;
strcat( newStr, cmd->GetName() );
strcat( newStr, " " );
lastCmd = cmd;
}
}
if( preserveParams )
{
/// Preserve the rest of the string after the matched command
ptr = strtok( nil, "\0" );
if( ptr != nil )
strcat( newStr, ptr );
}
// Copy back!
strcpy( line, newStr );
return true;
}
//// FindNestedPartialCmd ////////////////////////////////////////////////////
// Same as FindPartialCmd, only starts from the global group and searches
// everything. The string passed should only be a partial command sans
// groups. numToSkip specifies how many matches to skip before returning one
// (so if numToSkip = 1, then this will return the second match found).
hsBool pfConsoleEngine::FindNestedPartialCmd( char *line, UInt32 numToSkip, hsBool preserveParams )
{
pfConsoleCmd *cmd;
/// Somewhat easier than FindPartialCmd...
cmd = pfConsoleCmdGroup::GetBaseGroup()->FindNestedPartialCommand( line, &numToSkip );
if( cmd == nil )
return false;
/// Recurse back up and get the group hierarchy
line[ 0 ] = 0;
IBuildCmdNameRecurse( cmd->GetParent(), line );
strcat( line, cmd->GetName() );
strcat( line, " " );
if( preserveParams )
{
/// Preserve the rest of the string after the matched command
}
return true;
}
//// IBuildCmdNameRecurse ////////////////////////////////////////////////////
void pfConsoleEngine::IBuildCmdNameRecurse( pfConsoleCmdGroup *group, char *string )
{
if( group == nil || group == pfConsoleCmdGroup::GetBaseGroup() )
return;
IBuildCmdNameRecurse( group->GetParent(), string );
strcat( string, group->GetName() );
strcat( string, "." );
}

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==*/
//////////////////////////////////////////////////////////////////////////////
// //
// pfConsoleEngine Header //
// //
//// Description /////////////////////////////////////////////////////////////
// //
// The engine is where parsing and execution of console commands takes //
// place. It takes place independently of the interface, so that the //
// execution can happen from an INI file, from a screen-based console or //
// even a GUI interface. //
// //
//////////////////////////////////////////////////////////////////////////////
#ifndef _pfConsoleEngine_h
#define _pfConsoleEngine_h
#include "hsTypes.h"
#include "hsUtils.h"
//// pfConsoleEngine Class Definition ////////////////////////////////////////
class pfConsoleCmdParam;
class pfConsoleCmdGroup;
class pfConsoleEngine
{
private:
static const Int32 fMaxNumParams;
static const char fTokenSeparators[];
static const char fTokenGrpSeps[];
hsBool IConvertToParam( UInt8 type, char *string, pfConsoleCmdParam *param );
char fErrorMsg[ 128 ];
char fLastErrorLine[ 512 ];
void ISetErrorMsg( char *msg ) { hsStrncpy( fErrorMsg, msg, sizeof( fErrorMsg ) ); }
// Recursive function to build a string of the groups a command is in
void IBuildCmdNameRecurse( pfConsoleCmdGroup *group, char *string );
public:
pfConsoleEngine();
~pfConsoleEngine();
// Gets the signature for the command given (NO groups!)
const char *GetCmdSignature( char *name );
// Prints out the help for a given command (or group)
hsBool PrintCmdHelp( char *name, void (*PrintFn)( const char * ) );
// Breaks the given line into a command and parameters and runs the command
hsBool RunCommand( char *line, void (*PrintFn)( const char * ) );
// Executes the given file as a sequence of console commands
hsBool ExecuteFile( const char *fileName );
hsBool ExecuteFile( const wchar *fileName );
// Get the last reported error
const char *GetErrorMsg( void ) { return fErrorMsg; }
// Get the line for which the last reported error was for
const char *GetLastErrorLine( void ) { return fLastErrorLine; }
// Does command completion on a partially-complete console line
hsBool FindPartialCmd( char *line, hsBool findAgain = false, hsBool perserveParams = false );
// Does command completion without restrictions to any group, skipping the number of matches given
hsBool FindNestedPartialCmd( char *line, UInt32 numToSkip, hsBool perserveParams = false );
};
#endif //_pfConsoleEngine_h

View File

@ -0,0 +1,313 @@
/*==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 "pfDispatchLog.h"
#include "../plStatusLog/plStatusLog.h"
#include "../pnMessage/plMessage.h"
#include "../pnKeyedObject/plKey.h"
#include "hsWindows.h"
bool DumpSpecificMsgInfo(plMessage* msg, std::string& info);
plDispatchLog::plDispatchLog() :
fLog(nil),
fStartTicks(hsTimer::GetFullTickCount())
{
fLog = plStatusLogMgr::GetInstance().CreateStatusLog(20, "Dispatch.log", plStatusLog::kAlignToTop | plStatusLog::kFilledBackground | plStatusLog::kRawTimeStamp);
fIncludeTypes.SetSize(plFactory::GetNumClasses());
}
plDispatchLog::~plDispatchLog()
{
delete fLog;
}
void plDispatchLog::InitInstance()
{
static plDispatchLog dispatchLog;
fInstance = &dispatchLog;
}
void plDispatchLog::LogStatusBarChange(const char* name, const char* action)
{
fLog->AddLineF("----- Status bar '%s' %s -----", name, action);
#ifdef HS_BUILD_FOR_WIN32
MEMORYSTATUS ms;
GlobalMemoryStatus(&ms);
MEMORY_BASIC_INFORMATION mbi;
memset(&mbi, 0, sizeof(MEMORY_BASIC_INFORMATION));
// Note: this will return shared mem too on Win9x. There's a way to catch that, but it's too slow -Colin
UInt32 processMemUsed = 0;
void* curAddress = 0;
while (VirtualQuery(curAddress, &mbi, sizeof(MEMORY_BASIC_INFORMATION)) == sizeof(MEMORY_BASIC_INFORMATION))
{
if (mbi.State == MEM_COMMIT && mbi.Type == MEM_PRIVATE)
processMemUsed += mbi.RegionSize;
curAddress = ((BYTE*)mbi.BaseAddress) + mbi.RegionSize;
}
#define ToMB(mem) float(mem) / (1024.f*1024.f)
fLog->AddLineF("# Mem stats");
fLog->AddLineF("# Physical: %.1f MB used %.1f MB free", ToMB(ms.dwTotalPhys-ms.dwAvailPhys), ToMB(ms.dwAvailPhys));
fLog->AddLineF("# Virtual: %.1f MB used %.1f MB free", ToMB(ms.dwTotalVirtual-ms.dwAvailVirtual), ToMB(ms.dwAvailVirtual));
fLog->AddLineF("# Pagefile: %.1f MB used %.1f MB free", ToMB(ms.dwTotalPageFile-ms.dwAvailPageFile), ToMB(ms.dwAvailPageFile));
fLog->AddLineF("# Process: %.1f MB used", ToMB(processMemUsed));
#endif // HS_BUILD_FOR_WIN32
}
void plDispatchLog::LogLongReceive(const char* keyname, const char* className, UInt32 clonePlayerID, plMessage* msg, float ms)
{
std::string info;
if (DumpSpecificMsgInfo(msg, info))
fLog->AddLineF("%-30s[%7u](%-20s) took %6.1f ms to receive %s[%s]\n", keyname, clonePlayerID, className, ms, msg->ClassName(), info.c_str());
else
fLog->AddLineF("%-30s[%7u](%-20s) took %6.1f ms to receive %s\n", keyname, clonePlayerID, className, ms, msg->ClassName());
}
void plDispatchLog::DumpMsg(plMessage* msg, int numReceivers, int sendTimeMs, Int32 indent)
{
if (!msg)
return;
hsBool found=fIncludeTypes.IsBitSet(msg->ClassIndex());
if (found && !hsCheckBits(fFlags, plDispatchLogBase::kInclude))
// it's an exclude list and we found it
return;
if (!found && hsCheckBits(fFlags, plDispatchLogBase::kInclude))
// it's an include list and we didn't find it
return;
static hsScalar lastTime=0;
hsScalar curTime = (hsScalar)hsTimer::GetSysSeconds();
if (lastTime!=curTime)
{
// add linebreak for new frame
fLog->AddLine("\n");
}
float sendTime = hsTimer::FullTicksToMs(hsTimer::GetFullTickCount() - fStartTicks);
char indentStr[50];
indent = hsMinimum(indent, sizeof(indentStr)-1);
memset(indentStr, ' ', indent);
indentStr[indent] = '\0';
fLog->AddLineF("%sDispatched (%d) %d ms: time=%d CName=%s, sndr=%s, rcvr(%d)=%s, flags=0x%lx, tstamp=%f\n",
indentStr, numReceivers, sendTimeMs,
int(sendTime), msg->ClassName(), msg->fSender?msg->fSender->GetName():"nil",
msg->GetNumReceivers(), msg->GetNumReceivers() && msg->GetReceiver(0)
? msg->GetReceiver(0)->GetName():"nil",
msg->fBCastFlags, msg->fTimeStamp);
lastTime=curTime;
}
void plDispatchLog::AddFilterType(UInt16 hClass)
{
if (hClass>=plFactory::GetNumClasses())
return;
int i;
for( i = 0; i < plFactory::GetNumClasses(); i++ )
{
if( plFactory::DerivesFrom(hClass, i) )
AddFilterExactType(i);
}
}
void plDispatchLog::AddFilterExactType(UInt16 type)
{
if (type<plFactory::GetNumClasses())
fIncludeTypes.SetBit(type);
}
void plDispatchLog::RemoveFilterType(UInt16 hClass)
{
if (hClass>=plFactory::GetNumClasses())
return;
int i;
for( i = 0; i < plFactory::GetNumClasses(); i++ )
{
if( plFactory::DerivesFrom(hClass, i) )
RemoveFilterExactType(i);
}
}
void plDispatchLog::RemoveFilterExactType(UInt16 type)
{
if (type<plFactory::GetNumClasses())
fIncludeTypes.ClearBit(type);
}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
#include "../pnMessage/plClientMsg.h"
#include "../pfMessage/pfKIMsg.h"
#include "../pnKeyedObject/hsKeyedObject.h"
#include "../plResMgr/plKeyFinder.h"
#include "../plResMgr/plPageInfo.h"
static bool DumpSpecificMsgInfo(plMessage* msg, std::string& info)
{
#ifndef PLASMA_EXTERNAL_RELEASE // Don't bloat up the external release with all these strings
pfKIMsg* kiMsg = pfKIMsg::ConvertNoRef(msg);
if (kiMsg)
{
const char* typeName = "(unknown)";
#define PrintKIType(type) if (kiMsg->GetCommand() == pfKIMsg::##type) typeName = #type;
PrintKIType(kHACKChatMsg); // send chat message via pfKIMsg
PrintKIType(kEnterChatMode); // toggle chat mode
PrintKIType(kSetChatFadeDelay); // set the chat delay
PrintKIType(kSetTextChatAdminMode); // set the chat admin mode... not used (see CCR)
PrintKIType(kDisableKIandBB); // disable KI and blackbar (for things like AvaCusta)
PrintKIType(kEnableKIandBB); // re-enable the KI and blackbar
PrintKIType(kYesNoDialog); // display a Yes/No dialog
PrintKIType(kAddPlayerDevice); // add a device player list); such as imager
PrintKIType(kRemovePlayerDevice); // remove a device from player list
PrintKIType(kUpgradeKILevel); // upgrade the KI to higher level
PrintKIType(kDowngradeKILevel); // downgrade KI to next lower level
PrintKIType(kRateIt); // display the "RateIt"(tm) dialog
PrintKIType(kSetPrivateChatChannel); // set the private chat channel (for private rooms)
PrintKIType(kUnsetPrivateChatChannel); // unset private chat channel
PrintKIType(kStartBookAlert); // blink the book image on the blackbar
PrintKIType(kMiniBigKIToggle); // shortcut to toggling the miniKI/bigKI
PrintKIType(kKIPutAway); // shortcut to hiding all of the KI
PrintKIType(kChatAreaPageUp); // shortcut to paging up the chat area
PrintKIType(kChatAreaPageDown); // shortcut to paging down the chat area
PrintKIType(kChatAreaGoToBegin); // shortcut to going to the beginning of the chat area
PrintKIType(kChatAreaGoToEnd); // shortcut to going to the end of the chat area
PrintKIType(kKITakePicture); // shortcut to taking a picture in the KI
PrintKIType(kKICreateJournalNote); // shortcut to creating a journal note in the KI
PrintKIType(kKIToggleFade); // shortcut to toggle fade mode
PrintKIType(kKIToggleFadeEnable); // shortcut to toggling fade enabled
PrintKIType(kKIChatStatusMsg); // display status message in chat window
PrintKIType(kKILocalChatStatusMsg); // display status message in chat window
PrintKIType(kKIUpSizeFont); // bump up the size of the chat area font
PrintKIType(kKIDownSizeFont); // down size the font of the chat area
PrintKIType(kKIOpenYeehsaBook); // open the playerbook if not already open
PrintKIType(kKIOpenKI); // open up in degrees the KI
PrintKIType(kKIShowCCRHelp); // show the CCR help dialog
PrintKIType(kKICreateMarker); // create a marker
PrintKIType(kKICreateMarkerFolder); // create a marker folder in the current Age's journal folder
PrintKIType(kKILocalChatErrorMsg); // display error message in chat window
PrintKIType(kKIPhasedAllOn); // turn on all the phased KI functionality
PrintKIType(kKIPhasedAllOff); // turn off all the phased KI functionality
PrintKIType(kKIOKDialog); // display an OK dialog box (localized)
PrintKIType(kDisableYeeshaBook); // don't allow linking with the Yeesha book (gameplay)
PrintKIType(kEnableYeeshaBook); // re-allow linking with the Yeesha book
PrintKIType(kQuitDialog); // put up quit dialog
PrintKIType(kTempDisableKIandBB); // temp disable KI and blackbar (done by av system)
PrintKIType(kTempEnableKIandBB); // temp re-enable the KI and blackbar (done by av system)
PrintKIType(kDisableEntireYeeshaBook); // disable the entire Yeeshabook); not for gameplay); but prevent linking
PrintKIType(kEnableEntireYeeshaBook);
PrintKIType(kKIOKDialogNoQuit); // display OK dialog in the KI without quiting afterwards
PrintKIType(kGZUpdated); // the GZ game was updated
PrintKIType(kGZInRange); // a GZ marker is in range
PrintKIType(kGZOutRange); // GZ markers are out of range
PrintKIType(kUpgradeKIMarkerLevel); // upgrade the KI Marker level (current 0 and 1)
PrintKIType(kKIShowMiniKI); // force the miniKI up
PrintKIType(kGZFlashUpdate); // flash an update without saving (for animation of GZFill in)
PrintKIType(kNoCommand);
info = xtl::format("Type: %s Str: %s User: %s(%d) Delay: %f Int: %d",
typeName,
kiMsg->GetString() != "" ? kiMsg->GetString().c_str() : "(nil)",
kiMsg->GetUser() ? kiMsg->GetUser() : "(nil)",
kiMsg->GetPlayerID(),
kiMsg->GetDelay(),
kiMsg->GetIntValue());
return true;
}
plClientMsg* clientMsg = plClientMsg::ConvertNoRef(msg);
if (clientMsg)
{
#define PrintType(type) if (clientMsg->GetClientMsgFlag() == plClientMsg::##type) info = #type;
PrintType(kLoadRoom);
PrintType(kLoadRoomHold);
PrintType(kUnloadRoom);
PrintType(kLoadNextRoom);
PrintType(kInitComplete);
PrintType(kDisableRenderScene);
PrintType(kEnableRenderScene);
PrintType(kQuit);
PrintType(kLoadAgeKeys);
PrintType(kReleaseAgeKeys);
switch (clientMsg->GetClientMsgFlag())
{
case plClientMsg::kLoadRoom:
case plClientMsg::kLoadRoomHold:
case plClientMsg::kUnloadRoom:
{
info += " - Pages: ";
const std::vector<plLocation>& locs = clientMsg->GetRoomLocs();
for (int i = 0; i < locs.size(); i++)
{
const plLocation& loc = locs[i];
const plPageInfo* pageInfo = plKeyFinder::Instance().GetLocationInfo(loc);
if (pageInfo)
info += xtl::format("%s-%s ", pageInfo->GetAge(), pageInfo->GetPage());
}
}
break;
case plClientMsg::kLoadAgeKeys:
case plClientMsg::kReleaseAgeKeys:
info += xtl::format(" - Age: %s", clientMsg->GetAgeName());
break;
}
return true;
}
plRefMsg* refMsg = plRefMsg::ConvertNoRef(msg);
if (refMsg)
{
const char* typeName = nil;
#define GetType(type) if (refMsg->GetContext() == plRefMsg::##type) typeName = #type;
GetType(kOnCreate);
GetType(kOnDestroy);
GetType(kOnRequest);
GetType(kOnRemove);
GetType(kOnReplace);
xtl::format(info, "Obj: %s RefType: %s", refMsg->GetRef()->GetKeyName(), typeName);
return true;
}
#endif // PLASMA_EXTERNAL_RELEASE
return false;
}

View File

@ -0,0 +1,59 @@
/*==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 pfDispatchLog_inc
#define pfDispatchLog_inc
#include "../pnDispatch/plDispatchLogBase.h"
#include "hsBitVector.h"
class plStatusLog;
class plDispatchLog : public plDispatchLogBase
{
private:
hsBitVector fIncludeTypes; // include/exclude list
UInt64 fStartTicks;
plStatusLog* fLog;
public:
plDispatchLog();
~plDispatchLog();
static void InitInstance();
void AddFilterType(UInt16 type);
void AddFilterExactType(UInt16 type);
void RemoveFilterType(UInt16 type);
void RemoveFilterExactType(UInt16 type);
void LogStatusBarChange(const char* name, const char* action);
void LogLongReceive(const char* keyname, const char* className, UInt32 clonePlayerID, plMessage* msg, float ms);
void DumpMsg(plMessage* msg, int numReceivers, int sendTimeMs, Int32 indent);
};
#endif // pfDispatchLog_inc

View File

@ -0,0 +1,451 @@
/*==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==*/
//////////////////////////////////////////////////////////////////////////////
// //
// pfGameConsoleCommands //
// //
// Set of console commands that are actually meant for implementing //
// gameplay. Simpler than Python, easier to implement for programmers, and //
// far lower level, but should be used with extreme caution. //
// //
// Why? Because unlike normal console commands, which will eventually be //
// disabled in the shipping product (thus no danger of any fan cracking //
// them), these WILL be in the finished product. Debugging hacks and temp //
// workarounds to new features are NOT to be implemented here. //
// //
// Because of their nature, all Game. console commands should be approved //
// by Brice before checkin. //
// //
// Preferred method of adding Game. commands: //
// 1. Implement in normal console command groups (Debug. if nothing //
// else) //
// 2. Get the command approved //
// 3. Once command is tested and approved and deemed both worthy and //
// bug-free, cut-and-paste the command into the Game. group //
// //
//////////////////////////////////////////////////////////////////////////////
#ifdef PLASMA_EXTERNAL_RELEASE
#define LIMIT_CONSOLE_COMMANDS 1
#endif
#include "pfConsoleCmd.h"
#include "pfConsole.h"
#include "plPipeline.h"
#include "plgDispatch.h"
#include "../plGImage/plMipmap.h"
#include "../plGImage/plTGAWriter.h"
#include "../pfMessage/pfGameGUIMsg.h"
#include "../../NucleusLib/inc/hsResMgr.h"
#include "../pfGameGUIMgr/pfGUICtrlGenerator.h"
#include "../plAvatar/plAvatarMgr.h"
#include "../plAvatar/plAnimStage.h"
#include "../plAvatar/plAvBrainGeneric.h"
#include "../plAvatar/plAvBrainHuman.h"
#include "../plMessage/plAvatarMsg.h"
#include "../pnKeyedObject/plFixedKey.h"
#define PF_SANITY_CHECK( cond, msg ) { if( !( cond ) ) { PrintString( msg ); return; } }
//// DO NOT REMOVE!!!!
//// This is here so Microsoft VC won't decide to "optimize" this file out
//// DO NOT REMOVE!!!!
void pfConsoleCmdGroup::DummyJunior( void )
{
}
//// DO NOT REMOVE!!!!
//// plDoesFileExist //////////////////////////////////////////////////////////
// Utility function to determine whether the given file exists
static hsBool plDoesFileExist( const char *path )
{
hsUNIXStream stream;
if( !stream.Open( path, "rb" ) )
return false;
stream.Close();
return true;
}
//////////////////////////////////////////////////////////////////////////////
//// Game Group Commands /////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
PF_CONSOLE_GROUP( Game )
#ifndef LIMIT_CONSOLE_COMMANDS
PF_CONSOLE_CMD( Game, TakeScreenshot, "...", "Takes a shot of the current frame and saves it to the given file" )
{
hsAssert( pfConsole::GetPipeline() != nil, "Cannot use this command before pipeline initialization" );
plMipmap myMipmap;
char fileName[ 512 ];
UInt32 uniqueNumber;
if( numParams > 1 )
{
PrintString( "Too many parameters to TakeScreenshot" );
return;
}
else if( numParams == 1 )
strcpy( fileName, (char *)params[ 0 ] );
else
{
// Think up a filename
for( uniqueNumber = 1; uniqueNumber < 1000; uniqueNumber++ )
{
sprintf( fileName, "screen%03d.tga", uniqueNumber );
if( !plDoesFileExist( fileName ) )
break;
}
if( uniqueNumber == 1000 )
{
PrintString( "Out of filenames for TakeScreenshot" );
return;
}
}
if( !pfConsole::GetPipeline()->CaptureScreen( &myMipmap ) )
PrintString( "Error capturing screenshot" );
else
{
char str[ 512 ];
plTGAWriter::Instance().WriteMipmap( fileName, &myMipmap );
sprintf( str, "Screenshot written to '%s'.", fileName );
PrintString( str );
}
}
PF_CONSOLE_CMD( Game, LoadDialog, "string dlgName", "Loads the given GUI dialog into memory" )
{
plUoid lu( kGameGUIMgr_KEY );
plKey mgrKey = hsgResMgr::ResMgr()->FindKey( lu );
if( mgrKey )
{
pfGameGUIMsg *msg = TRACKED_NEW pfGameGUIMsg( mgrKey, pfGameGUIMsg::kLoadDialog );
msg->SetString( params[ 0 ] );
plgDispatch::MsgSend( msg );
}
}
PF_CONSOLE_CMD( Game, LoadLocalDialog, "string ageName, string dlgName", "Loads the given GUI dialog into memory" )
{
plUoid lu( kGameGUIMgr_KEY );
plKey mgrKey = hsgResMgr::ResMgr()->FindKey( lu );
if( mgrKey )
{
pfGameGUIMsg *msg = TRACKED_NEW pfGameGUIMsg( mgrKey, pfGameGUIMsg::kLoadDialog );
msg->SetString( params[ 1 ] );
msg->SetAge( params[ 0 ] );
plgDispatch::MsgSend( msg );
}
}
PF_CONSOLE_CMD( Game, ShowDialog, "string dlgName", "Shows the given GUI dialog" )
{
plUoid lu( kGameGUIMgr_KEY );
plKey mgrKey = hsgResMgr::ResMgr()->FindKey( lu );
if( mgrKey )
{
pfGameGUIMsg *msg = TRACKED_NEW pfGameGUIMsg( mgrKey, pfGameGUIMsg::kShowDialog );
msg->SetString( params[ 0 ] );
plgDispatch::MsgSend( msg );
}
}
PF_CONSOLE_CMD( Game, HideDialog, "string dlgName", "Hides the given GUI dialog" )
{
plUoid lu( kGameGUIMgr_KEY );
plKey mgrKey = hsgResMgr::ResMgr()->FindKey( lu );
if( mgrKey )
{
pfGameGUIMsg *msg = TRACKED_NEW pfGameGUIMsg( mgrKey, pfGameGUIMsg::kHideDialog );
msg->SetString( params[ 0 ] );
plgDispatch::MsgSend( msg );
}
}
PF_CONSOLE_CMD( Game, SwitchDialog, "string olddlgName, string newdlgName", "Hide olddlg and show newdlg" )
{
plUoid lu( kGameGUIMgr_KEY );
plKey mgrKey = hsgResMgr::ResMgr()->FindKey( lu );
if( mgrKey )
{
pfGameGUIMsg *msg = TRACKED_NEW pfGameGUIMsg( mgrKey, pfGameGUIMsg::kHideDialog );
msg->SetString( params[ 0 ] );
plgDispatch::MsgSend( msg );
pfGameGUIMsg *msg2 = TRACKED_NEW pfGameGUIMsg( mgrKey, pfGameGUIMsg::kShowDialog );
msg2->SetString( params[ 1 ] );
plgDispatch::MsgSend( msg2 );
}
}
PF_CONSOLE_SUBGROUP( Game, GUI )
#include "../pfGameGUIMgr/pfGUICtrlGenerator.h"
static hsColorRGBA sDynCtrlColor = hsColorRGBA().Set( 1, 1, 1, 1 ), sDynCtrlTextColor = hsColorRGBA().Set( 0, 0, 0, 1 );
PF_CONSOLE_CMD( Game_GUI, SetDynamicCtrlColor, "float bgRed, float bgGreen, float bgBlue, float textRed, float textGreen, float textBlue", "" )
{
sDynCtrlColor.Set( params[ 0 ], params[ 1 ], params[ 2 ], 1.f );
sDynCtrlTextColor.Set( params[ 3 ], params[ 4 ], params[ 5 ], 1.f );
}
PF_CONSOLE_CMD( Game_GUI, CreateRectButton, "string title, float x, float y, float width, float height, string command", "" )
{
pfGUICtrlGenerator::Instance().GenerateRectButton( params[ 0 ], params[ 1 ], params[ 2 ],
params[ 3 ], params[ 4 ],
params[ 5 ],
sDynCtrlColor, sDynCtrlTextColor );
}
PF_CONSOLE_CMD( Game_GUI, CreateRoundButton, "float x, float y, float radius, string command", "" )
{
pfGUICtrlGenerator::Instance().GenerateSphereButton( params[ 0 ], params[ 1 ], params[ 2 ],
params[ 3 ],
sDynCtrlColor );
}
PF_CONSOLE_CMD( Game_GUI, CreateDragBar, "float x, float y, float width, float height", "")
{
pfGUICtrlGenerator::Instance().GenerateDragBar( params[ 0 ], params[ 1 ], params[ 2 ], params[ 3 ], sDynCtrlColor );
}
PF_CONSOLE_CMD( Game_GUI, CreateDialog, "string name", "" )
{
pfGUICtrlGenerator::Instance().GenerateDialog( params[ 0 ] );
}
#endif
//#include "../pfKI/pfKI.h"
#include "../pfMessage/pfKIMsg.h"
PF_CONSOLE_CMD( Game, EnterChatMode, "", "Enters in-game chat mode" )
{
pfKIMsg* msg = TRACKED_NEW pfKIMsg(pfKIMsg::kEnterChatMode);
plgDispatch::MsgSend( msg );
}
PF_CONSOLE_CMD( Game, KIToggleMini, "", "Toggle between mini and big KI" )
{
pfKIMsg* msg = TRACKED_NEW pfKIMsg(pfKIMsg::kMiniBigKIToggle);
plgDispatch::MsgSend( msg );
}
PF_CONSOLE_CMD( Game, KIPutAway, "", "Put KI completely away" )
{
pfKIMsg* msg = TRACKED_NEW pfKIMsg(pfKIMsg::kKIPutAway);
plgDispatch::MsgSend( msg );
}
PF_CONSOLE_CMD( Game, KIChatPageUp, "", "Scroll chat display one page up" )
{
pfKIMsg* msg = TRACKED_NEW pfKIMsg(pfKIMsg::kChatAreaPageUp);
plgDispatch::MsgSend( msg );
}
PF_CONSOLE_CMD( Game, KIChatPageDown, "", "Scroll chat display one page down" )
{
pfKIMsg* msg = TRACKED_NEW pfKIMsg(pfKIMsg::kChatAreaPageDown);
plgDispatch::MsgSend( msg );
}
PF_CONSOLE_CMD( Game, KIChatToStart, "", "Scroll chat display to top of buffer" )
{
pfKIMsg* msg = TRACKED_NEW pfKIMsg(pfKIMsg::kChatAreaGoToBegin);
plgDispatch::MsgSend( msg );
}
PF_CONSOLE_CMD( Game, KIChatToEnd, "", "Scroll chat display to bottom of buffer" )
{
pfKIMsg* msg = TRACKED_NEW pfKIMsg(pfKIMsg::kChatAreaGoToEnd);
plgDispatch::MsgSend( msg );
}
PF_CONSOLE_CMD( Game, KITakePicture, "", "Take picture with KI" )
{
pfKIMsg* msg = TRACKED_NEW pfKIMsg(pfKIMsg::kKITakePicture);
plgDispatch::MsgSend( msg );
}
PF_CONSOLE_CMD( Game, KICreateJournal, "", "Create journal note entry" )
{
pfKIMsg* msg = TRACKED_NEW pfKIMsg(pfKIMsg::kKICreateJournalNote);
plgDispatch::MsgSend( msg );
}
PF_CONSOLE_CMD( Game, KIChatToggleFaded, "", "Toggle fade of chat display" )
{
pfKIMsg* msg = TRACKED_NEW pfKIMsg(pfKIMsg::kKIToggleFade);
plgDispatch::MsgSend( msg );
}
PF_CONSOLE_CMD( Game, KIChatToggleFadeEnable, "", "Toggle enable of chat fade" )
{
pfKIMsg* msg = TRACKED_NEW pfKIMsg(pfKIMsg::kKIToggleFadeEnable);
plgDispatch::MsgSend( msg );
}
PF_CONSOLE_CMD( Game, KIUpSizeFont, "", "Up size the KI font (chatarea)" )
{
pfKIMsg* msg = TRACKED_NEW pfKIMsg(pfKIMsg::kKIUpSizeFont);
plgDispatch::MsgSend( msg );
}
PF_CONSOLE_CMD( Game, KIDownSizeFont, "", "Down size the KI font (chatarea)" )
{
pfKIMsg* msg = TRACKED_NEW pfKIMsg(pfKIMsg::kKIDownSizeFont);
plgDispatch::MsgSend( msg );
}
PF_CONSOLE_CMD( Game, KIOpenYeeshaBook, "", "Open the player's Yeesha book" )
{
pfKIMsg* msg = TRACKED_NEW pfKIMsg(pfKIMsg::kKIOpenYeehsaBook);
plgDispatch::MsgSend( msg );
}
PF_CONSOLE_CMD( Game, KIOpenKI, "", "Open the KI a little at a time" )
{
pfKIMsg* msg = TRACKED_NEW pfKIMsg(pfKIMsg::kKIOpenKI);
plgDispatch::MsgSend( msg );
}
PF_CONSOLE_CMD( Game, KIHelp, "", "Open the CCR help dialog" )
{
pfKIMsg* msg = TRACKED_NEW pfKIMsg(pfKIMsg::kKIShowCCRHelp);
plgDispatch::MsgSend( msg );
}
PF_CONSOLE_CMD( Game, KICreateMarker, "", "Create marker in the working marker folder" )
{
pfKIMsg* msg = TRACKED_NEW pfKIMsg(pfKIMsg::kKICreateMarker);
plgDispatch::MsgSend( msg );
}
PF_CONSOLE_CMD( Game, KICreateMarkerFolder, "", "Create marker folder in current Age's journal folder" )
{
pfKIMsg* msg = TRACKED_NEW pfKIMsg(pfKIMsg::kKICreateMarkerFolder);
plgDispatch::MsgSend( msg );
}
PF_CONSOLE_CMD( Game, SetChatFadeDelay, "float delayInSecs", "Sets the time in seconds before the chat text disappears" )
{
// pfKI::GetInstance()->SetChatFadeDelay( params[ 0 ] );
pfKIMsg* msg = TRACKED_NEW pfKIMsg(pfKIMsg::kSetChatFadeDelay);
msg->SetDelay( params[0] );
plgDispatch::MsgSend( msg );
}
#include "../plAvatar/plArmatureMod.h"
PF_CONSOLE_CMD( Game, LimitAvatarLOD, "int newLOD", "Zero is (always) highest detail; 2 is (currently) lowest." )
{
int newLOD = params[0];
if(newLOD >= 0 && newLOD <= 2)
plArmatureLODMod::fMinLOD = newLOD;
}
PF_CONSOLE_SUBGROUP( Game, Emote) // Game.Emote.Shakefist
void Emote(const char *emotion, float fadeIn = 2.0, float fadeOut = 2.0)
{
plArmatureMod *avatar = plAvatarMgr::GetInstance()->GetLocalAvatar();
AvatarEmote(avatar, emotion);
}
PF_CONSOLE_CMD( Game_Emote, Wave, "", "")
{
Emote("Wave", 4.0, 1.0);
}
PF_CONSOLE_CMD( Game_Emote, Sneeze, "", "")
{
Emote("Sneeze");
}
PF_CONSOLE_CMD( Game_Emote, Dance, "", "")
{
Emote("Dance");
}
PF_CONSOLE_CMD( Game_Emote, Laugh, "", "")
{
Emote("Laugh");
}
PF_CONSOLE_CMD( Game_Emote, Clap, "", "")
{
Emote("Clap", 4.0, 3.0);
}
PF_CONSOLE_CMD( Game_Emote, Talk, "", "")
{
Emote("Talk");
}
PF_CONSOLE_CMD( Game_Emote, Sit, "", "")
{
plArmatureMod *avatar = plAvatarMgr::GetInstance()->GetLocalAvatar();
PushSimpleMultiStage(avatar, "SitDownGround", "SitIdleGround", "SitStandGround", true, true, plAGAnim::kBodyLower, plAvBrainGeneric::kSitOnGround);
}
#ifndef PLASMA_EXTERNAL_RELEASE
PF_CONSOLE_CMD( Game, SetLocalClientAsAdmin, "bool enable", "Makes chat messages from this client appear as admin messages" )
{
// pfKI::GetInstance()->SetTextChatAdminMode( (bool)params[ 0 ] );
pfKIMsg* msg = TRACKED_NEW pfKIMsg(pfKIMsg::kSetTextChatAdminMode);
msg->SetFlags( params[0] ? pfKIMsg::kAdminMsg : 0 );
plgDispatch::MsgSend( msg );
}
#endif
#include "../pfConditional/plObjectInBoxConditionalObject.h"
PF_CONSOLE_CMD( Game, BreakVolumeSensors, "bool break", "reverts to old broken volume sensor logic" )
{
bool b = params[ 0 ];
plVolumeSensorConditionalObject::makeBriceHappyVar = !b;
}

View File

@ -0,0 +1,42 @@
/*==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==*/
/*****************************************************************************
*
* $/Plasma20/Sources/Plasma/FeatureLib/pfCsrSrv/Pch.h
*
***/
#ifdef PLASMA20_SOURCES_PLASMA_FEATURELIB_PFCSRSRV_PCH_H
#error "Header $/Plasma20/Sources/Plasma/FeatureLib/pfCsrSrv/Pch.h included more than once"
#endif
#define PLASMA20_SOURCES_PLASMA_FEATURELIB_PFCSRSRV_PCH_H
#include "pfCsrSrv.h"
#pragma warning(push, 0)
#include "pfConsole/pfConsole.h"
#pragma warning(pop)

View File

@ -0,0 +1,145 @@
/*==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==*/
/*****************************************************************************
*
* $/Plasma20/Sources/Plasma/FeatureLib/pfCsrSrv/pfCsrSrv.cpp
*
***/
#include "Pch.h"
#pragma hdrstop
/*****************************************************************************
*
* Local types
*
***/
/*****************************************************************************
*
* Local data
*
***/
static bool s_running;
/*****************************************************************************
*
* Local functions
*
***/
//============================================================================
static bool Recv_ExecConsoleCmd (
SimpleNetConn * ,
CsrNet_ExecConsoleCmd * msg
) {
LogMsg(kLogPerf, L"pfCsrSrv: ExecConsoleCmd: %S", msg->cmd);
pfConsole::RunCommandAsync(msg->cmd);
return true;
}
//============================================================================
static bool OnMsg (
SimpleNetConn * conn,
SimpleNet_MsgHeader * msg
) {
bool result;
#define DISPATCH(a) case kCsrNet_##a: result = Recv_##a(conn, (CsrNet_##a *) msg); break
switch (msg->messageId) {
DISPATCH(ExecConsoleCmd);
default:
result = false;
}
#undef DISPATCH
return result;
}
//============================================================================
static void OnError (
SimpleNetConn * ,
ENetError error
) {
LogMsg(kLogPerf, L"pfCsrSrv NetError: %s", NetErrorToString(error));
}
//============================================================================
static bool QueryAccept (
void * ,
unsigned channel,
SimpleNetConn * ,
const NetAddress & addr
) {
wchar str[64];
NetAddressToString(addr, str, arrsize(str), kNetAddressFormatAll);
LogMsg(kLogPerf, L"pfCsrSrv: Accepted connection from %s", str);
return channel == kSimpleNetChannelCsr;
}
/*****************************************************************************
*
* Exports
*
***/
//============================================================================
void CsrSrvInitialize () {
#ifdef PLASMA_ENABLE_CSR_EXTERNAL
LogMsg(kLogPerf, L"pfCsrSrv: Initializing");
s_running = true;
SimpleNetInitialize();
SimpleNetCreateChannel(kSimpleNetChannelCsr, OnMsg, OnError);
SimpleNetStartListening(QueryAccept, nil);
#endif
}
//============================================================================
void CsrSrvShutdown () {
#ifdef PLASMA_ENABLE_CSR_EXTERNAL
LogMsg(kLogPerf, L"pfCsrSrv: Shutting down");
s_running = false;
SimpleNetStopListening();
SimpleNetDestroyChannel(kSimpleNetChannelCsr);
SimpleNetShutdown();
#endif
}

View File

@ -0,0 +1,50 @@
/*==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==*/
/*****************************************************************************
*
* $/Plasma20/Sources/Plasma/FeatureLib/pfCsrSrv/pfCsrSrv.h
*
***/
#ifndef PLASMA20_SOURCES_PLASMA_FEATURELIB_PFCSRSRV_PFCSRSRV_H
#define PLASMA20_SOURCES_PLASMA_FEATURELIB_PFCSRSRV_PFCSRSRV_H
#include "pnCsrNet/pnCsrNet.h"
/*****************************************************************************
*
* pfCsrSrv
* - Executes remote CSR commands received through pnCsrNet
*
***/
void CsrSrvInitialize ();
void CsrSrvShutdown ();
#endif // PLASMA20_SOURCES_PLASMA_FEATURELIB_PFCSRSRV_PFCSRSRV_H

View File

@ -0,0 +1,392 @@
/*==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==*/
//////////////////////////////////////////////////////////////////////////////
// //
// pfGUIButtonMod Definition //
// //
//////////////////////////////////////////////////////////////////////////////
#include "hsTypes.h"
#include "pfGUIButtonMod.h"
#include "pfGUIDraggableMod.h"
#include "pfGameGUIMgr.h"
#include "pfGUIControlHandlers.h"
#include "pfGUIDialogMod.h"
#include "../plInputCore/plInputInterface.h"
#include "../pnMessage/plRefMsg.h"
#include "../pfMessage/pfGameGUIMsg.h"
#include "../plMessage/plAnimCmdMsg.h"
#include "../plAvatar/plAGModifier.h"
#include "plgDispatch.h"
#include "hsResMgr.h"
//// Control Proc For Managing the Draggable /////////////////////////////////
class pfGUIButtonDragProc : public pfGUICtrlProcObject
{
protected:
pfGUICtrlProcObject *fOrigProc;
pfGUIButtonMod *fParent;
pfGUIDraggableMod *fDraggable;
hsBool fReportDrag;
public:
pfGUIButtonDragProc( pfGUIButtonMod *parent, pfGUIDraggableMod *draggable, pfGUICtrlProcObject *origProc, hsBool reportDrag )
{
fParent = parent;
fDraggable = draggable;
fOrigProc = origProc;
fReportDrag = reportDrag;
}
virtual void DoSomething( pfGUIControlMod *ctrl )
{
// The draggable was let up, so now we stop dragging, disable the draggable again, and pass
// on the event to our original proc
if( fOrigProc != nil && fParent->IsTriggering() )
fOrigProc->DoSomething( ctrl );
if (!fParent->IsButtonDown())
fParent->StopDragging( false );
}
virtual void HandleExtendedEvent( pfGUIControlMod *ctrl, UInt32 event )
{
if( event == pfGUIDraggableMod::kDragging )
{
// First test if we're inside our button (if so, we stop dragging)
if( fParent->PointInBounds( fDraggable->GetLastMousePt() ) )
{
// Cancel the drag
fParent->StopDragging( true );
return;
}
if( !fReportDrag )
return;
}
if( fOrigProc != nil )
fOrigProc->HandleExtendedEvent( ctrl, event );
}
virtual void UserCallback( UInt32 userValue )
{
if( fOrigProc != nil )
fOrigProc->UserCallback( userValue );
}
};
void pfGUIButtonMod::StopDragging( hsBool cancel )
{
fDraggable->StopDragging( cancel );
fDraggable->SetVisible( false );
fDraggable->SetHandler( fOrigHandler );
fOrigHandler = nil;
if( !fOrigReportedDrag )
fDraggable->ClearFlag( pfGUIDraggableMod::kReportDragging );
// Steal interest back
fDialog->SetControlOfInterest( this );
}
void pfGUIButtonMod::StartDragging( void )
{
fOrigReportedDrag = fDraggable->HasFlag( pfGUIDraggableMod::kReportDragging );
fDraggable->SetFlag( pfGUIDraggableMod::kReportDragging );
fOrigHandler = fDraggable->GetHandler();
fDraggable->SetVisible( true );
fDraggable->SetHandler( TRACKED_NEW pfGUIButtonDragProc( this, fDraggable, fOrigHandler, fOrigReportedDrag ) );
fDraggable->HandleMouseDown( fOrigMouseDownPt, 0 );
}
//// Constructor/Destructor //////////////////////////////////////////////////
pfGUIButtonMod::pfGUIButtonMod()
{
fAnimName = nil;
fMouseOverAnimName = nil;
fDraggable = nil;
fOrigHandler = nil;
fClicking = false;
fTriggering = false;
fNotifyType = kNotifyOnUp;
SetFlag( kWantsInterest );
}
pfGUIButtonMod::~pfGUIButtonMod()
{
delete [] fAnimName;
delete [] fMouseOverAnimName;
}
//// IEval ///////////////////////////////////////////////////////////////////
hsBool pfGUIButtonMod::IEval( double secs, hsScalar del, UInt32 dirty )
{
return pfGUIControlMod::IEval( secs, del, dirty );
}
//// MsgReceive //////////////////////////////////////////////////////////////
hsBool pfGUIButtonMod::MsgReceive( plMessage *msg )
{
plGenRefMsg *refMsg = plGenRefMsg::ConvertNoRef( msg );
if( refMsg != nil && refMsg->fType == kRefDraggable )
{
if( refMsg->GetContext() & ( plRefMsg::kOnCreate | plRefMsg::kOnRequest | plRefMsg::kOnReplace ) )
{
fDraggable = pfGUIDraggableMod::ConvertNoRef( refMsg->GetRef() );
fDraggable->SetVisible( false ); // Disable until we're dragging
}
else
fDraggable = nil;
return true;
}
return pfGUIControlMod::MsgReceive( msg );
}
//// Read/Write //////////////////////////////////////////////////////////////
void pfGUIButtonMod::Read( hsStream *s, hsResMgr *mgr )
{
pfGUIControlMod::Read(s, mgr);
fAnimationKeys.Reset();
UInt32 i, count = s->ReadSwap32();
for( i = 0; i < count; i++ )
fAnimationKeys.Append( mgr->ReadKey( s ) );
fAnimName = s->ReadSafeString();
fMouseOverAnimKeys.Reset();
count = s->ReadSwap32();
for( i = 0; i < count; i++ )
fMouseOverAnimKeys.Append( mgr->ReadKey( s ) );
fMouseOverAnimName = s->ReadSafeString();
fNotifyType = s->ReadSwap32();
mgr->ReadKeyNotifyMe( s, TRACKED_NEW plGenRefMsg( GetKey(), plRefMsg::kOnCreate, -1, kRefDraggable ), plRefFlags::kActiveRef );
}
void pfGUIButtonMod::Write( hsStream *s, hsResMgr *mgr )
{
pfGUIControlMod::Write( s, mgr );
UInt32 i, count = fAnimationKeys.GetCount();
s->WriteSwap32( count );
for( i = 0; i < count; i++ )
mgr->WriteKey( s, fAnimationKeys[ i ] );
s->WriteSafeString( fAnimName );
count = fMouseOverAnimKeys.GetCount();
s->WriteSwap32( count );
for( i = 0; i < count; i++ )
mgr->WriteKey( s, fMouseOverAnimKeys[ i ] );
s->WriteSafeString( fMouseOverAnimName );
s->WriteSwap32( fNotifyType );
mgr->WriteKey( s, fDraggable != nil ? fDraggable->GetKey() : nil );
}
//// UpdateBounds ////////////////////////////////////////////////////////////
void pfGUIButtonMod::UpdateBounds( hsMatrix44 *invXformMatrix, hsBool force )
{
pfGUIControlMod::UpdateBounds( invXformMatrix, force );
if( fAnimationKeys.GetCount() > 0 || fMouseOverAnimKeys.GetCount() > 0 )
fBoundsValid = false;
}
//// HandleMouseDown/Up //////////////////////////////////////////////////////
void pfGUIButtonMod::HandleMouseDown( hsPoint3 &mousePt, UInt8 modifiers )
{
fClicking = true;
if( fAnimationKeys.GetCount() > 0 )
{
plAnimCmdMsg *msg = TRACKED_NEW plAnimCmdMsg();
msg->SetCmd( plAnimCmdMsg::kContinue );
msg->SetCmd( plAnimCmdMsg::kSetForewards );
msg->SetCmd( plAnimCmdMsg::kGoToBegin );
msg->SetAnimName( fAnimName );
msg->AddReceivers( fAnimationKeys );
plgDispatch::MsgSend( msg );
}
IPlaySound( kMouseDown );
fOrigMouseDownPt = mousePt;
if ( fNotifyType == kNotifyOnDown || fNotifyType == kNotifyOnUpAndDown)
{
fTriggering = true;
DoSomething();
fTriggering = false;
}
}
void pfGUIButtonMod::HandleMouseUp( hsPoint3 &mousePt, UInt8 modifiers )
{
// make sure that we got the down click first
if ( !fClicking )
return;
fClicking = false;
if( fAnimationKeys.GetCount() > 0 )
{
plAnimCmdMsg *msg = TRACKED_NEW plAnimCmdMsg();
msg->SetCmd( plAnimCmdMsg::kContinue );
msg->SetCmd( plAnimCmdMsg::kSetBackwards );
msg->SetCmd( plAnimCmdMsg::kGoToEnd );
msg->SetAnimName( fAnimName );
msg->AddReceivers( fAnimationKeys );
plgDispatch::MsgSend( msg );
}
IPlaySound( kMouseUp );
// Don't run the command if the mouse is outside our bounds
if( !fBounds.IsInside( &mousePt ) && fNotifyType != kNotifyOnUpAndDown )
return;
if ( fNotifyType == kNotifyOnUp || fNotifyType == kNotifyOnUpAndDown)
fTriggering = true;
DoSomething();
fTriggering = false;
}
void pfGUIButtonMod::HandleMouseDrag( hsPoint3 &mousePt, UInt8 modifiers )
{
if( !fClicking )
return;
if( fDraggable == nil )
return;
if( !fDraggable->IsVisible() )
{
// Are we outside ourselves?
if( !PointInBounds( mousePt ) )
{
// Yes, start dragging
StartDragging();
// Hand off our interest to the draggable
fDialog->SetControlOfInterest( fDraggable );
}
}
}
void pfGUIButtonMod::SetNotifyType(Int32 kind)
{
fNotifyType = kind;
}
Int32 pfGUIButtonMod::GetNotifyType()
{
return fNotifyType;
}
hsBool pfGUIButtonMod::IsButtonDown()
{
return fClicking;
}
//// SetInteresting //////////////////////////////////////////////////////////
// Overridden to play mouse over animation when we're interesting
void pfGUIButtonMod::SetInteresting( hsBool i )
{
pfGUIControlMod::SetInteresting( i );
if( fMouseOverAnimKeys.GetCount() )
{
plAnimCmdMsg *msg = TRACKED_NEW plAnimCmdMsg();
msg->SetCmd( plAnimCmdMsg::kContinue );
msg->SetCmd( fInteresting ? plAnimCmdMsg::kSetForewards : plAnimCmdMsg::kSetBackwards );
msg->SetAnimName( fMouseOverAnimName );
msg->AddReceivers( fMouseOverAnimKeys );
plgDispatch::MsgSend( msg );
}
if( i )
IPlaySound( kMouseOver );
else
IPlaySound( kMouseOff );
}
void pfGUIButtonMod::SetAnimationKeys( hsTArray<plKey> &keys, const char *name )
{
fAnimationKeys = keys;
delete [] fAnimName;
if( name != nil )
{
fAnimName = TRACKED_NEW char[ strlen( name ) + 1 ];
strcpy( fAnimName, name );
}
else
fAnimName = nil;
}
void pfGUIButtonMod::SetMouseOverAnimKeys( hsTArray<plKey> &keys, const char *name )
{
fMouseOverAnimKeys = keys;
delete [] fMouseOverAnimName;
if( name != nil )
{
fMouseOverAnimName = TRACKED_NEW char[ strlen( name ) + 1 ];
strcpy( fMouseOverAnimName, name );
}
else
fMouseOverAnimName = nil;
}
//// IGetDesiredCursor ///////////////////////////////////////////////////////
UInt32 pfGUIButtonMod::IGetDesiredCursor( void ) const
{
if( fHandler == nil )
return 0;
if( fClicking )
return plInputInterface::kCursorClicked;
return plInputInterface::kCursorPoised;
}

View File

@ -0,0 +1,121 @@
/*==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==*/
//////////////////////////////////////////////////////////////////////////////
// //
// pfGUIButtonMod Header //
// //
//////////////////////////////////////////////////////////////////////////////
#ifndef _pfGUIButtonMod_h
#define _pfGUIButtonMod_h
#include "pfGUIControlMod.h"
class plMessage;
class plPostEffectMod;
class plAGMasterMod;
class pfGUIDraggableMod;
class pfGUIButtonMod : public pfGUIControlMod
{
protected:
hsTArray<plKey> fAnimationKeys;
char *fAnimName;
hsTArray<plKey> fMouseOverAnimKeys;
char *fMouseOverAnimName;
hsBool fClicking;
hsBool fTriggering;
hsPoint3 fOrigMouseDownPt;
pfGUIDraggableMod *fDraggable;
pfGUICtrlProcObject *fOrigHandler;
hsBool fOrigReportedDrag;
Int32 fNotifyType;
virtual hsBool IEval( double secs, hsScalar del, UInt32 dirty ); // called only by owner object's Eval()
virtual UInt32 IGetDesiredCursor( void ) const; // As specified in plInputInterface.h
public:
pfGUIButtonMod();
virtual ~pfGUIButtonMod();
CLASSNAME_REGISTER( pfGUIButtonMod );
GETINTERFACE_ANY( pfGUIButtonMod, pfGUIControlMod );
virtual hsBool MsgReceive( plMessage* pMsg );
virtual void Read( hsStream* s, hsResMgr* mgr );
virtual void Write( hsStream* s, hsResMgr* mgr );
virtual void SetInteresting( hsBool i );
virtual void HandleMouseDown( hsPoint3 &mousePt, UInt8 modifiers );
virtual void HandleMouseUp( hsPoint3 &mousePt, UInt8 modifiers );
virtual void HandleMouseDrag( hsPoint3 &mousePt, UInt8 modifiers );
virtual void UpdateBounds( hsMatrix44 *invXformMatrix = nil, hsBool force = false );
virtual void SetNotifyType(Int32 kind);
virtual Int32 GetNotifyType();
virtual hsBool IsButtonDown();
virtual hsBool IsTriggering() { return fTriggering; }
enum SoundEvents
{
kMouseDown,
kMouseUp,
kMouseOver,
kMouseOff
};
enum
{
kRefDraggable = kRefDerivedStart
};
enum NotifyType
{
kNotifyOnUp = 0,
kNotifyOnDown,
kNotifyOnUpAndDown
};
void StartDragging( void );
void StopDragging( hsBool cancel );
// Export only
void SetAnimationKeys( hsTArray<plKey> &keys, const char *name );
void SetMouseOverAnimKeys( hsTArray<plKey> &keys, const char *name );
};
#endif // _pfGUIButtonMod_h

View File

@ -0,0 +1,206 @@
/*==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==*/
//////////////////////////////////////////////////////////////////////////////
// //
// pfGUICheckBoxCtrl Definition //
// //
// Almost like buttons, only they keep their stated (pressed/unpressed) //
// when you click them, instead of reverting on mouse up. //
// //
//////////////////////////////////////////////////////////////////////////////
#include "hsTypes.h"
#include "pfGUICheckBoxCtrl.h"
#include "pfGameGUIMgr.h"
#include "../plInputCore/plInputInterface.h"
#include "../pnMessage/plRefMsg.h"
#include "../pfMessage/pfGameGUIMsg.h"
#include "../plMessage/plAnimCmdMsg.h"
#include "../plAvatar/plAGModifier.h"
#include "plgDispatch.h"
#include "hsResMgr.h"
//// Constructor/Destructor //////////////////////////////////////////////////
pfGUICheckBoxCtrl::pfGUICheckBoxCtrl()
{
fAnimName = nil;
SetFlag( kWantsInterest );
fChecked = false;
fClicking = false;
fPlaySound = true;
}
pfGUICheckBoxCtrl::~pfGUICheckBoxCtrl()
{
delete [] fAnimName;
}
//// IEval ///////////////////////////////////////////////////////////////////
hsBool pfGUICheckBoxCtrl::IEval( double secs, hsScalar del, UInt32 dirty )
{
return pfGUIControlMod::IEval( secs, del, dirty );
}
//// MsgReceive //////////////////////////////////////////////////////////////
hsBool pfGUICheckBoxCtrl::MsgReceive( plMessage *msg )
{
return pfGUIControlMod::MsgReceive( msg );
}
//// Read/Write //////////////////////////////////////////////////////////////
void pfGUICheckBoxCtrl::Read( hsStream *s, hsResMgr *mgr )
{
pfGUIControlMod::Read(s, mgr);
fAnimationKeys.Reset();
UInt32 i, count = s->ReadSwap32();
for( i = 0; i < count; i++ )
fAnimationKeys.Append( mgr->ReadKey( s ) );
fAnimName = s->ReadSafeString();
fChecked = s->ReadBool();
}
void pfGUICheckBoxCtrl::Write( hsStream *s, hsResMgr *mgr )
{
pfGUIControlMod::Write( s, mgr );
UInt32 i, count = fAnimationKeys.GetCount();
s->WriteSwap32( count );
for( i = 0; i < count; i++ )
mgr->WriteKey( s, fAnimationKeys[ i ] );
s->WriteSafeString( fAnimName );
s->WriteBool( fChecked );
}
//// UpdateBounds ////////////////////////////////////////////////////////////
void pfGUICheckBoxCtrl::UpdateBounds( hsMatrix44 *invXformMatrix, hsBool force )
{
pfGUIControlMod::UpdateBounds( invXformMatrix, force );
if( fAnimationKeys.GetCount() > 0 )
fBoundsValid = false;
}
//// HandleMouseDown/Up //////////////////////////////////////////////////////
void pfGUICheckBoxCtrl::HandleMouseDown( hsPoint3 &mousePt, UInt8 modifiers )
{
fClicking = true;
if(fPlaySound)
IPlaySound( kMouseDown );
}
void pfGUICheckBoxCtrl::HandleMouseUp( hsPoint3 &mousePt, UInt8 modifiers )
{
if( fClicking )
{
fClicking = false;
if(fPlaySound)
IPlaySound( kMouseUp );
// Don't run the command if the mouse is outside our bounds
if( fBounds.IsInside( &mousePt ) )
{
SetChecked( !fChecked );
DoSomething();
}
}
}
//// SetChecked //////////////////////////////////////////////////////////////
void pfGUICheckBoxCtrl::SetChecked( hsBool checked, hsBool immediate /*= false*/ )
{
fChecked = checked;
if( fAnimationKeys.GetCount() > 0 )
{
plAnimCmdMsg *msg = TRACKED_NEW plAnimCmdMsg();
if( fChecked )
{
// Moving to true
if( immediate )
{
msg->SetCmd( plAnimCmdMsg::kGoToEnd );
}
else
{
msg->SetCmd( plAnimCmdMsg::kContinue );
msg->SetCmd( plAnimCmdMsg::kSetForewards );
msg->SetCmd( plAnimCmdMsg::kGoToBegin );
}
}
else
{
// Moving to false
if( immediate )
{
msg->SetCmd( plAnimCmdMsg::kGoToBegin );
}
else
{
msg->SetCmd( plAnimCmdMsg::kContinue );
msg->SetCmd( plAnimCmdMsg::kSetBackwards );
msg->SetCmd( plAnimCmdMsg::kGoToEnd );
}
}
msg->SetAnimName( fAnimName );
msg->AddReceivers( fAnimationKeys );
plgDispatch::MsgSend( msg );
}
}
void pfGUICheckBoxCtrl::SetAnimationKeys( hsTArray<plKey> &keys, const char *name )
{
fAnimationKeys = keys;
delete [] fAnimName;
if( name != nil )
{
fAnimName = TRACKED_NEW char[ strlen( name ) + 1 ];
strcpy( fAnimName, name );
}
else
fAnimName = nil;
}
//// IGetDesiredCursor ///////////////////////////////////////////////////////
UInt32 pfGUICheckBoxCtrl::IGetDesiredCursor( void ) const
{
if( fClicking )
return plInputInterface::kCursorClicked;
return plInputInterface::kCursorPoised;
}

View File

@ -0,0 +1,95 @@
/*==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==*/
//////////////////////////////////////////////////////////////////////////////
// //
// pfGUICheckBoxCtrl Header //
// //
//////////////////////////////////////////////////////////////////////////////
#ifndef _pfGUICheckBoxCtrl_h
#define _pfGUICheckBoxCtrl_h
#include "pfGUIControlMod.h"
class plMessage;
class plPostEffectMod;
class plAGMasterMod;
class pfGUICheckBoxCtrl : public pfGUIControlMod
{
protected:
hsTArray<plKey> fAnimationKeys;
char *fAnimName;
hsBool fClicking;
hsBool fChecked;
hsBool fPlaySound;
virtual hsBool IEval( double secs, hsScalar del, UInt32 dirty ); // called only by owner object's Eval()
virtual UInt32 IGetDesiredCursor( void ) const; // As specified in plInputInterface.h
public:
pfGUICheckBoxCtrl();
virtual ~pfGUICheckBoxCtrl();
CLASSNAME_REGISTER( pfGUICheckBoxCtrl );
GETINTERFACE_ANY( pfGUICheckBoxCtrl, pfGUIControlMod );
virtual hsBool MsgReceive( plMessage* pMsg );
virtual void Read( hsStream* s, hsResMgr* mgr );
virtual void Write( hsStream* s, hsResMgr* mgr );
virtual void HandleMouseDown( hsPoint3 &mousePt, UInt8 modifiers );
virtual void HandleMouseUp( hsPoint3 &mousePt, UInt8 modifiers );
virtual void UpdateBounds( hsMatrix44 *invXformMatrix = nil, hsBool force = false );
void SetChecked( hsBool checked, hsBool immediate = false );
hsBool IsChecked( void ) { return fChecked; }
void DontPlaySounds() { fPlaySound = false; } // should the checkbox play sounds?
const hsTArray<plKey> &GetAnimationKeys( void ) const { return fAnimationKeys; }
const char *GetAnimationName( void ) const { return fAnimName; }
enum SoundEvents
{
kMouseDown,
kMouseUp,
kMouseOver,
kMouseOff
};
// Export only
void SetAnimationKeys( hsTArray<plKey> &keys, const char *name );
};
#endif // _pfGUICheckBoxCtrl_h

Some files were not shown because too many files have changed in this diff Show More