Developer Store
Support
Member Forums

Screenshots
FAQ
Documentation
License
Known Issues
Downloads

MMOWorkshop BACK!

PyTorque
TGB Web Browser


jburch

hallsofvalhalla - Been A while
xapken - Wizards and Champions
J.C. Smith - The Repopulation - 0.5.2 Build Notes
EmpireGames - Elementals in Rise of Heroes
Empire Games - WarPath.
jaidurn - Warcall 0.0.1.0 build notes
medafor - Final detailing of models
Thamior - Presence system GONE! [May 25th 2009)]
... MORE BLOGS!

Building a MMO
Wow I had no idea....
Quest Remnants of Chaos
Checking to see if anyone is sti...
Well here I am again :)
T3D and MMOKit
afx 2.0
Terrain specularity [video]
Torque T3D MMO Kit
[3dFoin] Dragon Bug
Index: C:/newtgeawork/repopulation_code/trunk/engine/source/T3D/fx/particleEmitter.h
===================================================================
--- C:/newtgeawork/repopulation_code/trunk/engine/source/T3D/fx/particleEmitter.h	(revision 72)
+++ C:/newtgeawork/repopulation_code/trunk/engine/source/T3D/fx/particleEmitter.h	(revision 73)
@@ -18,6 +18,8 @@
 #include "gfx/gfxDevice.h"
 #endif
 
+#include "gfx/gfxTextureHandle.h"
+
 class  ParticleData;
 
 //*****************************************************************************
@@ -187,6 +189,25 @@
                       const F32      radius,
                       const Point3F& velocity,
                       S32 count);
+
+// Begin MMO Kit
+   void setLifeTimeOverride (F32 lifetime){mLifetimeMS = lifetime;}
+   void setTextureOverride(GFXTexHandle& texHandle)
+   {
+      if (!texHandle)
+      {
+         mTextureOverrideHandle = texHandle;
+         return;
+      }
+
+      if (mTextureOverrideHandle && mTextureOverrideHandle.mBitmapName == texHandle.mBitmapName)
+         return;
+
+      mTextureOverrideHandle = texHandle;
+   }
+  public:
+   GFXTexHandle mTextureOverrideHandle;
+// End MMO Kit
    /// @}
 
    bool mDead;
Index: C:/newtgeawork/repopulation_code/trunk/engine/source/T3D/fx/particleEmitterNode.cpp
===================================================================
--- C:/newtgeawork/repopulation_code/trunk/engine/source/T3D/fx/particleEmitterNode.cpp	(revision 72)
+++ C:/newtgeawork/repopulation_code/trunk/engine/source/T3D/fx/particleEmitterNode.cpp	(revision 73)
@@ -8,6 +8,10 @@
 #include "core/bitStream.h"
 #include "T3D/fx/particleEmitter.h"
 #include "math/mathIO.h"
+// Begin MMO Kit
+#include "T3D/gameConnection.h"
+#include "T3D/shapeBase.h"
+// End MMO Kit
 
 IMPLEMENT_CO_DATABLOCK_V1(ParticleEmitterNodeData);
 IMPLEMENT_CO_NETOBJECT_V1(ParticleEmitterNode);
@@ -99,6 +103,11 @@
    mEmitterDatablockId = 0;
    mEmitter            = NULL;
    mVelocity           = 1.0;
+// Begin MMO Kit
+   mMaxDist            = 40.f;
+   mTextureOverride = StringTable->insert("");
+   mParentId = 0;
+// End MMO Kit
 }
 
 //-----------------------------------------------------------------------------
@@ -117,6 +126,11 @@
    Parent::initPersistFields();
    addField("emitter",  TypeParticleEmitterDataPtr, Offset(mEmitterDatablock, ParticleEmitterNode));
    addField("velocity", TypeF32,                    Offset(mVelocity,         ParticleEmitterNode));
+// Begin MMO Kit
+   addField("maxDist", TypeF32,                    Offset(mMaxDist,         ParticleEmitterNode));
+   addField("textureOverride", TypeFilename, Offset(mTextureOverride,ParticleEmitterNode));
+   addField("parentId", TypeS32, Offset(mParentId,ParticleEmitterNode));
+// End MMO Kit
 }
 
 //-----------------------------------------------------------------------------
@@ -149,14 +163,35 @@
       mEmitter = pEmitter;
    }
 
-   mObjBox.min.set(-0.5, -0.5, -0.5);
-   mObjBox.max.set( 0.5,  0.5,  0.5);
+// Begin MMO Kit
+/* Original TGE Code:
+    mObjBox.min.set(-0.5, -0.5, -0.5);
+    mObjBox.max.set( 0.5,  0.5,  0.5);
+*/
+   F32 s = mMaxDist/2.f;
+
+   mObjBox.min.set(-s, -s, -s);
+   mObjBox.max.set( s,  s,  s);
+// End MMO Kit
    resetWorldBox();
    addToScene();
 
    return true;
 }
 
+// Begin MMO Kit
+void ParticleEmitterNode::inspectPostApply()
+{
+   Parent::inspectPostApply();
+   F32 s = mMaxDist/2.f;
+
+   mObjBox.min.set(-s, -s, -s);
+   mObjBox.max.set( s,  s,  s);
+   resetWorldBox();
+   
+}
+// End MMO Kit
+
 //-----------------------------------------------------------------------------
 // onRemove
 //-----------------------------------------------------------------------------
@@ -196,12 +231,50 @@
 {
    Parent::advanceTime(dt);
 
+// Begin MMO Kit
+   GameConnection* pConnection = GameConnection::getConnectionToServer();
+   if (pConnection)
+   {
+      ShapeBase* sb = dynamic_cast<ShapeBase*>(pConnection->getControlObject());
+      if (sb)
+      {
+         Point3F pos = sb->getPosition();
+         pos -= getPosition();
+         if (pos.len() > mMaxDist)
+            return;
+      }
+      else
+         return;
+   }
+   else
+      return;
+// End MMO Kit
+
    Point3F emitPoint, emitVelocity;
    Point3F emitAxis(0, 0, 1);
    getTransform().mulV(emitAxis);
    getTransform().getColumn(3, &emitPoint);
    emitVelocity = emitAxis * mVelocity;
 
+// Begin MMO Kit
+   if (mParentId)
+   {
+      SceneObject* p = dynamic_cast<SceneObject* > (Sim::findObject(mParentId));
+      if (p)
+      {
+         emitPoint = p->getPosition();
+         emitPoint.z += 1.0f;
+         setPosition(emitPoint);
+      }
+      else
+      {
+         mParentId = 0;
+      }
+   }
+
+   mEmitter->setTextureOverride(mTextureOverrideHandle);
+// End MMO Kit
+
    mEmitter->emitParticles(emitPoint, emitPoint,
                            emitAxis,
                            emitVelocity, (U32)(dt * mDataBlock->timeMultiple * 1000.0f));
@@ -214,6 +287,45 @@
 {
    U32 retMask = Parent::packUpdate(con, mask, stream);
 
+ // Begin MMO Kit
+   if (mTextureOverride && dStrlen(mTextureOverride))
+   {
+      stream->writeFlag(true);
+      stream->writeString(mTextureOverride);
+   }
+   else
+      stream->writeFlag(false);
+
+   if (mParentId)
+   {
+      SimObject* p = Sim::findObject(mParentId);
+      if (p)
+      {
+         S32 gIndex = con->getGhostIndex((NetObject*)p);
+
+         if (gIndex!=-1)
+         {
+            stream->writeFlag( true );
+            stream->writeInt(gIndex, NetConnection::GhostIdBitSize);
+         }
+         else
+         {
+            stream->writeFlag( false );
+         }
+      }
+      else
+      {
+         stream->writeFlag( false );
+      }
+      
+   }
+   else
+      stream->writeFlag( false );
+   
+
+   stream->write(mMaxDist);
+// End MMO Kit
+
    mathWrite(*stream, getTransform());
    mathWrite(*stream, getScale());
    if( stream->writeFlag(mEmitterDatablock != NULL) )
@@ -234,6 +346,39 @@
 
    MatrixF temp;
    Point3F tempScale;
+// Begin MMO Kit
+   if (stream->readFlag())
+   {
+      char  buffer[256];
+
+      stream->readString(buffer);
+      if (dStricmp(mTextureOverride,buffer))
+      {
+         mTextureOverride = StringTable->insert(buffer);
+         if (dStrlen(mTextureOverride))
+            mTextureOverrideHandle = GFXTexHandle( mTextureOverride, &GFXDefaultPersistentProfile );
+         else
+            mTextureOverrideHandle = NULL;         
+      }
+   }
+   else
+      mTextureOverrideHandle = NULL;
+
+   if (stream->readFlag())
+   {
+      S32 gIndex = stream->readInt(NetConnection::GhostIdBitSize);
+      SceneObject* parent = static_cast<SceneObject*>(con->resolveGhost(gIndex));
+      if (parent)
+         mParentId = parent->getId();
+      else
+         mParentId = 0;
+
+   }
+   else
+      mParentId = 0;
+   
+   stream->read(&mMaxDist);
+// End MMO Kit
    mathRead(*stream, &temp);
    mathRead(*stream, &tempScale);
 
Index: C:/newtgeawork/repopulation_code/trunk/engine/source/T3D/fx/particleEmitterNode.h
===================================================================
--- C:/newtgeawork/repopulation_code/trunk/engine/source/T3D/fx/particleEmitterNode.h	(revision 72)
+++ C:/newtgeawork/repopulation_code/trunk/engine/source/T3D/fx/particleEmitterNode.h	(revision 73)
@@ -10,6 +10,7 @@
 #include "T3D/gameBase.h"
 #endif
 
+#include "gfx/gfxTextureHandle.h"
 class ParticleEmitterData;
 class ParticleEmitter;
 
@@ -63,7 +64,13 @@
 
    SimObjectPtr<ParticleEmitter> mEmitter;
    F32              mVelocity;
-
+// Begin MMO Kit
+   F32              mMaxDist;
+ 
+   StringTableEntry mTextureOverride;
+   GFXTexHandle    mTextureOverrideHandle;
+   S32              mParentId;
+// End MMO Kit
   public:
    ParticleEmitterNode();
    ~ParticleEmitterNode();
@@ -81,6 +88,7 @@
    void unpackUpdate(NetConnection *conn,           BitStream* stream);
 
    void setEmitterDataBlock(ParticleEmitterData* data);
+   void inspectPostApply(); // <-- MMO Kit
 };
 
 #endif // _H_PARTICLEEMISSIONDUMMY
Index: C:/newtgeawork/repopulation_code/trunk/engine/source/T3D/fx/particleEmitter.cpp
===================================================================
--- C:/newtgeawork/repopulation_code/trunk/engine/source/T3D/fx/particleEmitter.cpp	(revision 72)
+++ C:/newtgeawork/repopulation_code/trunk/engine/source/T3D/fx/particleEmitter.cpp	(revision 73)
@@ -14,6 +14,10 @@
 #include "renderInstance/renderInstMgr.h"
 #include "T3D/gameProcess.h"
 
+// Begin MMO Kit
+#include "T3D/gameConnection.h"
+// End MMO Kit
+
 static ParticleEmitterData gDefaultEmitterData;
 Point3F ParticleEmitter::mWindVelocity( 0.0, 0.0, 0.0 );
 

Particles from equipped weapons

Index: C:/newtgeawork/repopulation_code/trunk/engine/source/T3D/shapeBase.h
===================================================================
--- C:/newtgeawork/repopulation_code/trunk/engine/source/T3D/shapeBase.h	(revision 73)
+++ C:/newtgeawork/repopulation_code/trunk/engine/source/T3D/shapeBase.h	(revision 74)
@@ -1456,8 +1456,10 @@
    virtual void getRenderEyeTransform(MatrixF* mat);
    /// @}
 
+// Begin MMO Kit
+   void triggerParticleNode(StringTableEntry node,StringTableEntry particle,StringTableEntry texture,int duration);
+// End MMO Kit
 
-
    /// @name Screen Flashing
    /// @{
 
@@ -1695,6 +1697,24 @@
    
    void setSelectedObjectId(SimObjectId id,U8 charIndex); 
    SimObjectId getSelectedObjectId(U8 charIndex) { return mSelectedObjectId[charIndex]; } 
+
+   struct ParticleNodeEmitter {
+   S32 node;
+   F32 time;
+   F32 duration;
+   SimObjectPtr<ParticleEmitter> emitter;
+   };
+
+   StringTableEntry     mEquippedParticle0;
+   StringTableEntry     mEquippedParticle1;
+   StringTableEntry     mEquippedParticleTexture0;
+   StringTableEntry     mEquippedParticleTexture1;
+   ParticleNodeEmitter* mEquipPNode0;
+   ParticleNodeEmitter* mEquipPNode1;
+
+
+   Vector<ParticleNodeEmitter*> mParticleNodeEmitters;
+
    virtual const Point3F& getHeadRotation() { return mAppliedForce; }
    //virtual const Point3F& getRotation() { return mAppliedForce; }
 
Index: C:/newtgeawork/repopulation_code/trunk/engine/source/T3D/shapeBase.cpp
===================================================================
--- C:/newtgeawork/repopulation_code/trunk/engine/source/T3D/shapeBase.cpp	(revision 73)
+++ C:/newtgeawork/repopulation_code/trunk/engine/source/T3D/shapeBase.cpp	(revision 74)
@@ -47,6 +47,7 @@
 #include "interior/interior.h"
 #include "rpg/fx/daynight.h"
 #include "t3d/fx/fxSunLight.h"
+#include "T3D/fx/particleEmitter.h"
 // End MMO Kit 
 
 IMPLEMENT_CO_DATABLOCK_V1(ShapeBaseData);
@@ -881,6 +882,13 @@
   mCameraZoom = 2.5;
   mRole = StringTable->insert("");
 
+  mEquipPNode0 = NULL;
+  mEquipPNode1 = NULL;
+  mEquippedParticle0 = NULL;
+  mEquippedParticle1 = NULL;
+  mEquippedParticleTexture0 = NULL;
+  mEquippedParticleTexture1 = NULL;
+
   //spell_being_cast = NULL;
 
   // End MMO Kit
@@ -1282,7 +1290,61 @@
    for (int i = 0; i < MaxMountedImages; i++)
       if (mMountedImageList[i].dataBlock)
          updateImageAnimation(i,dt);
+   // Begin MMO Kit 
+   Vector<ParticleNodeEmitter*> newlist;
 
+   //hack, just throw these in the list as the list is created below
+
+   if(mEquipPNode0)
+       mParticleNodeEmitters.push_back(mEquipPNode0);
+
+   if(mEquipPNode1)
+       mParticleNodeEmitters.push_back(mEquipPNode1);
+
+   for (Vector<ParticleNodeEmitter*>::iterator itr = mParticleNodeEmitters.begin(); itr != mParticleNodeEmitters.end(); itr++)
+   {
+      ParticleNodeEmitter* pne = *itr;
+      if (pne->duration!=-1)
+        pne->time-=dt;
+      if (pne->time<=0.f && pne->duration!=-1)
+      {         
+         pne->emitter->deleteObject();
+         delete pne;
+      }
+      else
+      {
+         MatrixF mat;
+         Point3F pos,axis;
+         mat = getTransform();
+         if (pne->node!=-1)
+         {
+            MatrixF nmat=mShapeInstance->mNodeTransforms[pne->node];
+            nmat.getColumn(3,&pos);
+            pos*=getScale();
+            nmat.setColumn(3,pos);
+            mat.mul(nmat);
+         }
+         
+         
+         mat.getColumn(3,&pos);
+         mat.getColumn(1,&axis);
+
+         pne->emitter->emitParticles(pos,true,axis,getVelocity(),(U32) (dt * 1000));
+
+         if (*itr == mEquipPNode0 || *itr == mEquipPNode1)
+             continue;
+
+         newlist.push_back(*itr);
+         
+      }
+
+   }
+
+   mParticleNodeEmitters.clear();
+
+   for (Vector<ParticleNodeEmitter*>::iterator itr = newlist.begin(); itr != newlist.end(); itr++)
+      mParticleNodeEmitters.push_back(*itr);
+
 // MMO Kit Change (comment out)
 /*
    // Cloaking takes 0.5 seconds
@@ -3325,10 +3387,32 @@
          con->packNetStringHandleU(stream, mShapeNameHandle);
       }
       if (stream->writeFlag(mask & ShieldMask)) {
-         // MMO Kit Change (comment out)
-         // stream->writeNormalVector(mShieldNormal, ShieldNormalBits);
-         // stream->writeFloat( getEnergyValue(), EnergyLevelBits );
-         // End MMO Kit
+          // Begin MMO Kit
+          /* Original TGE Code:
+          stream->writeNormalVector(mShieldNormal, ShieldNormalBits);
+          stream->writeFloat( getEnergyValue(), EnergyLevelBits );
+          */
+          stream->writeString(mEquippedParticle0);
+          stream->writeString(mEquippedParticle1);
+          stream->writeString(mEquippedParticleTexture0);
+          stream->writeString(mEquippedParticleTexture1);
+
+          if (mEquippedParticle0 && dStrlen(mEquippedParticle0))
+          {
+              ParticleEmitterData *pdata=NULL;
+              Sim::findObject(mEquippedParticle0,pdata);
+              AssertISV(pdata,"BAD Particle Emitter");
+              stream->writeRangedU32(pdata->getId(),DataBlockObjectIdFirst,DataBlockObjectIdLast);
+          }
+
+          if (mEquippedParticle1 && dStrlen(mEquippedParticle1))
+          {
+              ParticleEmitterData *pdata=NULL;
+              Sim::findObject(mEquippedParticle1,pdata);
+              AssertISV(pdata,"BAD Particle Emitter");
+              stream->writeRangedU32(pdata->getId(),DataBlockObjectIdFirst,DataBlockObjectIdLast);
+          }
+          // End MMO Kit
       }
       if (stream->writeFlag(mask & InvincibleMask)) {
          stream->write(mInvincibleTime);
@@ -3584,16 +3668,145 @@
       }
       if(stream->readFlag())     // ShieldMask
       {
-         // MMO Kit change (commented out)
-         /*
-         // Cloaking, Shield, and invul masking
-         Point3F shieldNormal;
-         stream->readNormalVector(&shieldNormal, ShieldNormalBits);
-         
-         // CodeReview [bjg 4/6/07] This is our energy level - why aren't we storing it? Was in a
-         // local variable called energyPercent.
-         stream->readFloat(EnergyLevelBits);
-         */
+          // Begin MMO Kit
+          /* Original TGE Code:
+          // Cloaking, Shield, and invul masking
+          Point3F shieldNormal;
+          stream->readNormalVector(&shieldNormal, ShieldNormalBits);
+          F32 energyPercent = stream->readFloat(EnergyLevelBits);
+          */
+          mEquippedParticle0 = stream->readSTString();
+          mEquippedParticle1 = stream->readSTString();
+          mEquippedParticleTexture0 = stream->readSTString();
+          mEquippedParticleTexture1 = stream->readSTString();
+
+          char buffer[256];
+          if (mEquippedParticleTexture0 && dStrnicmp("~/",mEquippedParticleTexture0,17))
+          {
+              dSprintf(buffer,256,"~/data/shapes/particles/%s",mEquippedParticleTexture0);
+              mEquippedParticleTexture0 = StringTable->insert(buffer);
+          }
+          if (mEquippedParticleTexture1 && dStrnicmp("~/",mEquippedParticleTexture1,17))
+          {
+              dSprintf(buffer,256,"~/data/shapes/particles/%s",mEquippedParticleTexture1);
+              mEquippedParticleTexture1 = StringTable->insert(buffer);
+          }
+
+          ParticleEmitterData* pdata0=NULL;
+          ParticleEmitterData* pdata1=NULL;
+
+          if (mEquippedParticle0 && dStrlen(mEquippedParticle0))
+          {
+              U32 particleID = stream->readRangedU32( DataBlockObjectIdFirst, DataBlockObjectIdLast );
+              Sim::findObject( particleID, pdata0 );
+          }
+
+          if (mEquippedParticle1 && dStrlen(mEquippedParticle1))
+          {
+              U32 particleID = stream->readRangedU32( DataBlockObjectIdFirst, DataBlockObjectIdLast );
+              Sim::findObject( particleID, pdata1 );
+          }
+
+          //clearing
+          if (!mEquippedParticle0 && mEquipPNode0)
+          {
+              mEquipPNode0->emitter->deleteObject();
+              delete mEquipPNode0;
+              mEquipPNode0 = NULL;
+          }
+
+          if (!mEquippedParticle1 && mEquipPNode1)
+          {
+              mEquipPNode1->emitter->deleteObject();
+              delete mEquipPNode1;
+              mEquipPNode1 = NULL;
+          }
+
+          //same?
+          if (mEquippedParticle0 && mEquipPNode0)
+          {
+              ParticleEmitter* emitter = mEquipPNode0->emitter;
+              if (dStricmp(emitter->getDataBlock()->getName(),mEquippedParticle0)|| (emitter->mTextureOverrideHandle && 
+                  dStricmp(emitter->mTextureOverrideHandle.mBitmapName,mEquippedParticleTexture0)))
+              {
+                  dPrintf("Deleting Particle Node\n");
+                  emitter->deleteObject();
+                  delete mEquipPNode0;
+                  mEquipPNode0 = NULL;
+              }
+          }
+
+          //same?
+          if (mEquippedParticle1 && mEquipPNode1)
+          {
+              ParticleEmitter* emitter = mEquipPNode1->emitter;
+              if (dStricmp(emitter->getDataBlock()->getName(),mEquippedParticle1)|| (emitter->mTextureOverrideHandle && 
+                  dStricmp(emitter->mTextureOverrideHandle.mBitmapName,mEquippedParticleTexture1)))
+              {
+                  dPrintf("Deleting Particle Node\n");
+                  emitter->deleteObject();
+                  delete mEquipPNode1;
+                  mEquipPNode1 = NULL;
+              }
+          }
+
+          //create?
+          if (pdata0 && !mEquipPNode0)
+          {
+              S32 nindex = getShape()->findNode(StringTable->insert("Mount0"));
+              if (nindex>=0)
+              {
+
+                  ShapeBase::ParticleNodeEmitter* pne = new ShapeBase::ParticleNodeEmitter;
+                  ParticleEmitter* emitter = new ParticleEmitter;
+
+                  mEquipPNode0 = pne;
+                  pne->node = nindex;
+                  pne->emitter = emitter;
+                  pne->duration = -1;
+                  pne->time = -1;
+
+                  emitter->onNewDataBlock(pdata0);
+                  emitter->registerObject();
+
+                  if (mEquippedParticleTexture0 && dStrlen(mEquippedParticleTexture0))
+                  {
+                      
+                      GFXTexHandle th = GFXTexHandle(mEquippedParticleTexture0, &GFXDefaultPersistentProfile );
+                      emitter->setTextureOverride(th);
+                  }
+
+                  
+              }
+          }
+          //create?
+          if (pdata1 && !mEquipPNode1)
+          {
+              S32 nindex = getShape()->findNode(StringTable->insert("Mount1"));
+              if (nindex>=0)
+              {
+
+                  ShapeBase::ParticleNodeEmitter* pne = new ShapeBase::ParticleNodeEmitter;
+                  ParticleEmitter* emitter = new ParticleEmitter;
+
+                  mEquipPNode1 = pne;
+                  pne->node = nindex;
+                  pne->emitter = emitter;
+                  pne->duration = -1;
+                  pne->time = -1;
+
+                  emitter->onNewDataBlock(pdata1);
+                  emitter->registerObject();
+
+                  if (mEquippedParticleTexture1 && dStrlen(mEquippedParticleTexture1))
+                  {
+                      GFXTexHandle th = GFXTexHandle(mEquippedParticleTexture1, &GFXDefaultPersistentProfile );
+                      emitter->setTextureOverride(th);
+                  }
+
+              }
+          }
+          // End MMO Kit
         }
 
       if (stream->readFlag()) 
@@ -4666,6 +4879,261 @@
 	//Con::executef(this->getControllingClient() ,2,"selectObject",scriptThis());
 } 
 //--------------------------------------------------------------------------
+// Particle Node Emitters -- MMO KIT
+//--------------------------------------------------------------------------
+//
+class ParticleNodeEvent : public NetEvent
+{
+   typedef NetEvent Parent;
+
+public:
+
+   ParticleNodeEvent();
+
+   void setData(ShapeBase* shape,StringTableEntry node,StringTableEntry particle,StringTableEntry texture,S32 duration);
+
+   ShapeBase*        mShape;
+   StringTableEntry  mNode;
+   StringTableEntry  mParticle;
+   StringTableEntry  mTexture;
+   S32               mDuration;
+
+public:
+   
+   ~ParticleNodeEvent();
+
+   void pack(NetConnection*, BitStream*);
+   void write(NetConnection*, BitStream*){}
+   void unpack(NetConnection*, BitStream*);
+   void process(NetConnection*);
+
+   DECLARE_CONOBJECT(ParticleNodeEvent);
+};
+IMPLEMENT_CO_CLIENTEVENT_V1(ParticleNodeEvent);
+
+ParticleNodeEvent::ParticleNodeEvent()
+{
+   mShape = NULL;
+   mNode = NULL;
+   mTexture = NULL;
+   mParticle = NULL;
+   mDuration = NULL;
+
+}
+
+void ParticleNodeEvent::setData(ShapeBase* shape,StringTableEntry node,StringTableEntry particle,StringTableEntry texture,S32 duration)
+{
+   mShape = shape;
+   mNode = node;
+   mTexture = texture;
+   mParticle =particle;
+   mDuration = duration;
+
+}
+
+ParticleNodeEvent::~ParticleNodeEvent()
+{
+
+}
+
+void ParticleNodeEvent::pack(NetConnection* con, BitStream* stream)
+{
+
+   S32 ghostIndex = con->getGhostIndex(mShape);
+   stream->writeRangedU32(U32(ghostIndex), 0, NetConnection::MaxGhostCount);
+   stream->writeString(mNode);
+
+   if (!mParticle)
+       stream->writeFlag(false); //clearing
+   else
+   {
+       stream->writeFlag(true);
+       ParticleEmitterData *pdata=NULL;
+       Sim::findObject(mParticle,pdata);
+       AssertISV(pdata,"BAD Particle Emitter");
+       stream->writeRangedU32(pdata->getId(),DataBlockObjectIdFirst,DataBlockObjectIdLast);
+       stream->writeString(mTexture);
+       stream->write(mDuration);
+   }
+
+}
+
+class ParticleNodeEmitter;
+
+void ParticleNodeEvent::unpack(NetConnection* con, BitStream* stream)
+{
+   // target id
+   S32 mTargetID    = stream->readRangedU32(0, NetConnection::MaxGhostCount);
+   ParticleEmitterData *pdata = NULL;
+
+   NetObject* pObject = con->resolveGhost(mTargetID);
+   if( pObject != NULL )
+   {
+      mShape = dynamic_cast<ShapeBase*>(pObject);
+   }
+
+    mNode = stream->readSTString(true);
+
+    if (stream->readFlag())
+    {
+        U32 particleID = stream->readRangedU32( DataBlockObjectIdFirst, DataBlockObjectIdLast );
+        Sim::findObject( particleID, pdata );
+
+        mTexture = stream->readSTString(false);
+        stream->read(&mDuration);
+
+        if (mShape && mDuration && pdata)
+        {    
+
+            if (pdata)
+            {
+                S32 nindex = mShape->getShape()->findNode(mNode);
+                if (nindex>=0)
+                {
+
+                    ShapeBase::ParticleNodeEmitter* pne = new ShapeBase::ParticleNodeEmitter;
+                    ParticleEmitter* emitter = new ParticleEmitter;
+
+                    pne->node = nindex;
+                    pne->emitter = emitter;
+                    pne->duration = mDuration;
+                    if (mDuration ==-1)
+                        pne->time = -1; //give the Particles time
+                    else
+                        pne->time = mDuration*2; //give the Particles time
+
+                    if (mTexture && dStrlen(mTexture))
+                    {
+                        GFXTexHandle th = GFXTexHandle( mTexture, &GFXDefaultPersistentProfile );
+                        emitter->setTextureOverride(th);
+                    }
+
+                    emitter->onNewDataBlock(pdata);
+                    emitter->registerObject();
+
+                    if (mDuration != -1)
+                        emitter->setLifeTimeOverride(mDuration*1000);
+                    //emitter->deleteWhenEmpty();
+
+                    mShape->mParticleNodeEmitters.push_back(pne);
+                }
+            }
+        }
+
+    }
+    else
+    {
+        //clearing
+        S32 nindex = mShape->getShape()->findNode(mNode);
+        if (nindex>=0)
+        {
+            Vector<ShapeBase::ParticleNodeEmitter*> newlist;
+
+            for (Vector<ShapeBase::ParticleNodeEmitter*>::iterator itr = mShape->mParticleNodeEmitters.begin(); itr != mShape->mParticleNodeEmitters.end(); itr++)
+            {
+                ShapeBase::ParticleNodeEmitter* pne = *itr;
+                if (pne->duration==-1 && pne->node ==nindex)
+                {         
+                    pne->emitter->deleteObject();
+                    delete pne;
+                }
+                else
+                    newlist.push_back(*itr);
+            }
+
+            mShape->mParticleNodeEmitters.clear();
+
+            for (Vector<ShapeBase::ParticleNodeEmitter*>::iterator itr = newlist.begin(); itr != newlist.end(); itr++)
+                mShape->mParticleNodeEmitters.push_back(*itr);
+
+        }
+    }
+
+}
+
+void ParticleNodeEvent::process(NetConnection*)
+{
+}
+
+
+
+
+void ShapeBase::triggerParticleNode(StringTableEntry node,StringTableEntry particle,StringTableEntry texture,int duration)
+{
+   S32 nindex = mShapeInstance->getShape()->findNode(node);
+
+
+   if (nindex < 0)
+      return;
+
+   if (duration==-1 || !particle)
+   {
+       setMaskBits(ShieldMask);
+       if (!dStricmp(node,"Mount0"))
+       {
+           mEquippedParticle0 = particle;
+           mEquippedParticleTexture0 = texture;
+       }
+       else
+       {
+           mEquippedParticle1 = particle;
+           mEquippedParticleTexture1 = texture;
+       }
+       return;
+   }
+   
+   
+   ParticleEmitterData *pdata=NULL;
+   
+   if (particle)
+   {
+       Sim::findObject(particle,pdata);
+       if (!pdata)
+        return;
+   }
+
+   SimGroup* pClientGroup = Sim::getClientGroup();
+   for (SimGroup::iterator itr = pClientGroup->begin(); itr != pClientGroup->end(); itr++)
+   {
+      GameConnection* nc = dynamic_cast<GameConnection*>(*itr);
+
+      if (nc->getGhostIndex(this)==-1)
+         continue;
+
+      if (nc && nc->getControlObject())
+      {
+         F32 len = (nc->getControlObject()->getPosition()-getPosition()).lenSquared();
+         if (len > 100.f*100.f)
+            continue;
+      }
+      else
+         continue;
+
+
+      ParticleNodeEvent* pEvent = new ParticleNodeEvent;
+      pEvent->setData(this,node,particle,texture,duration);
+      nc->postNetEvent(pEvent);
+   }
+
+   
+
+}
+
+//clears permanent on node, permanent is marked as a duration OF -1
+ConsoleMethod( ShapeBase, clearParticleNode, void, 3, 3, "node")
+{
+    object->triggerParticleNode(argv[2],NULL,NULL,0);
+}
+
+
+ConsoleMethod( ShapeBase, triggerParticleNode, void, 6, 6, "node,particle,texture,duration")
+{
+   object->triggerParticleNode(argv[2],argv[3],argv[4],dAtoi(argv[5]));
+}
+
+// End Particle Emitters MMO Kit
+
+//--------------------------------------------------------------------------
 // Start of HideMesh v2 Part
 //--------------------------------------------------------------------------
 
Index: C:/newtgeawork/repopulation_code/trunk/engine/source/T3D/fx/particleEmitter.cpp
===================================================================
--- C:/newtgeawork/repopulation_code/trunk/engine/source/T3D/fx/particleEmitter.cpp	(revision 73)
+++ C:/newtgeawork/repopulation_code/trunk/engine/source/T3D/fx/particleEmitter.cpp	(revision 74)
@@ -937,7 +937,9 @@
    //   DestBlend is in the lower 4.
    ri->transFlags = ((mDataBlock->srcBlendFactor << 4) & 0xf0) | (mDataBlock->dstBlendFactor & 0x0f);
    // use first particle's texture unless there is an emitter texture to override it
-   if (mDataBlock->textureHandle)
+   if (mTextureOverrideHandle)
+     ri->miscTex = &*(mTextureOverrideHandle);
+   else if (mDataBlock->textureHandle)
      ri->miscTex = &*(mDataBlock->textureHandle);
    else
      ri->miscTex = &*(part_list_head.next->dataBlock->textureHandle);