Game Development Community

dev|Pro Game Development Curriculum

1. MXG Weapon Mod - Decals Depending on Material

by Marcus L · 05/02/2010 (11:37 am) · 11 comments

Tested on: 1.1b2
Note: I will only keep my resources up to date until next stable release (1.1 final)

This resource will give you the ability to define custom decals for your materials. The system is not perfect but it'll work for now.

Ok so I'm going to do it this way:
Where it says // Added, it means that the line is added.
Where it says // Removed, it means that the line is removed.
Where it says // Changed, it means that the line is changed.
Where it says ..., it means that there is code between what ever that was last written.
Whenever it says ..., there will be an comment below describing what function it is.

I recommend you using CTRL + F to find where to put the code blocks. Remember to backup before installing.

Now, to install this resource start by editing your materials/materialDefinition.cpp:
...
//In the includes
#include "sfx/sfxTrack.h"
#include "sfx/sfxTypes.h"
#include "T3D/decal/decalManager.h" // Added
#include "T3D/decal/decalData.h" // Added
...
//In Material::Material()
   mFootstepSoundId = -1;     mImpactSoundId = -1;
   mFootstepSoundCustom = 0;  mImpactSoundCustom = 0;
   mCustomDecal = NULL; // Added
...
//In Material::initPersistFields()
addField( "customImpactSound", TypeSFXTrackName,    Offset( mImpactSoundCustom, Material ),
         "The sound to play when the player impacts on the surface with a velocity equal or greater than PlayerData::groundImpactMinSpeed.  "
         "If this is set, it overrides #impactSoundId.  This field is useful for directly assigning custom impact sounds to materials "
         "without having to rely on the PlayerData sound assignment.nn"
         "@warn Be aware that materials are client-side objects.  This means that the SFXTracks assigned to materials must be client-side, too." );
		 
	  addField( "customDecal",		   TYPEID< DecalData >(),    Offset( mCustomDecal, Material ) ); // Added
...
//Custom code, put it where you want
void Material::setCustomDecal(DecalData *decal)
{
	this->mCustomDecal = decal;
}

ConsoleMethod( Material, setCustomDecal, void, 3, 3, 
              "setCustomDecal: Set a spesific decal for assigned material." )
{
   DecalData* decal;
   if (Sim::findObject(argv[2],decal)) 
	  object->setCustomDecal(decal);
}

Now for materials/materialDefinition.h:
...
//In the friend class definitions
class MaterialSoundProfile;
class MaterialPhysicsProfile;
class DecalData; // Added
...
//In public of class Material
SFXTrack* mFootstepSoundCustom;
SFXTrack* mImpactSoundCustom;
DecalData* mCustomDecal; // Added
...
//Same
   virtual bool isAutoGenerated() const { return mAutoGenerated; }
   virtual void setAutoGenerated(bool isAutoGenerated) { mAutoGenerated = isAutoGenerated; }
   virtual void setCustomDecal(DecalData *decal); // Added

Next is T3D/projectile.cpp:
...
//In the includes
#include "T3D/decal/decalData.h"
#include "T3D/lightDescription.h"
#include "materials/baseMatInstance.h" // Added
...
//In ProjectileData::ProjectileData()
decal = NULL;
decalId = 0;
customDecal = false; // Added
...
//In ProjectileData::initPersistFields()
   addField("explosion", TYPEID< ExplosionData >(), Offset(explosion, ProjectileData));
   addField("waterExplosion", TYPEID< ExplosionData >(), Offset(waterExplosion, ProjectileData));

   addField("customDecal", TypeBool, Offset(customDecal, ProjectileData)); // Added
...
//In Projectile::simulate( F32 dt )
   // disable the source objects collision reponse while we determine
   // if the projectile is capable of moving from the old position
   // to the new position, otherwise we'll hit ourself

   //MXG: Some change in beta 2 made this change required // Added
   //if ( mSourceObject.isValid() ) // Changed
      //mSourceObject->disableCollision(); // Changed
   disableCollision();
...
//Same
         //if(mSourceObject) // Changed
            //mSourceObject->enableCollision(); // Changed

		 // Get the rayCasts material info // Added ->
		 Material* material = ( rInfo.material ? dynamic_cast< Material* >( rInfo.material->getMaterial() ) : 0 );
		 DecalData* decal = mDataBlock->decal;

		 // Checks if the material info is valid, and then check if it should
		 // apply the custom decal
		 if(material != NULL)
		 {
			 if(mDataBlock->customDecal == true && material->mCustomDecal != NULL)
			 {
				 decal = material->mCustomDecal;
			 }
		 } // Added <-
...
//Same, in Projectile::simulate(F32 dt)
         onCollision(rInfo.point, rInfo.normal, rInfo.object);
		 explode(rInfo.point, rInfo.normal, decal, objectType ); // Changed
...
//In Projectile::unpackUpdate(NetConnection* con, BitStream* stream)
          mathRead( *stream, &explodeNormal );
          stream->read( &mCollideHitType );
          DecalData* decal = NULL; // Added

          explode(explodePoint, explodeNormal, decal, mCollideHitType); // Changed
...
//In void Projectile::explode( const Point3F &p, const Point3F &n, const U32 collideType )
void Projectile::explode( const Point3F &p, const Point3F &n, DecalData* decal, const U32 collideType ) // Changed
{
...
//Same
            pExplosion = NULL;
         }
      }

      // Client (impact) decal.
      if (decal != NULL) // Changed
		  gDecalManager->addDecal( p, n, 0.0f, decal ); // Changed

...
//

Lastly T3D/projectile.h:
...
//In public of class ProjectileData
   DecalData *decal;                   // (impact) Decal Datablock
   S32 decalId;                        // (impact) Decal ID
   bool customDecal; // Added
...
//In protected of class Projectile
virtual void explode(const Point3F& p, const Point3F& n, DecalData* decal, const U32 collideType ); // Changed

Start (re)building while you add the next part.

The next part is the part I would like to avoid, this will be fixed in a later resource
make a new .cs file scripts/server/customMatFX.cs and add the following in it:
function loadCustomDecals()
{
   // Where material is the name/id of the material
   // and decal is the name/id of the decal
   material.setCustomDecal(decal); 
}
and execute it by adding
exec("./radiusDamage.cs");
exec("./staticShape.cs");
exec("./customMatFX.cs"); // Added
and adding this line to game/gameCore.cs:
$Game::Schedule = schedule($Game::Duration * 1000 * 60, 0, "onGameDurationEnd");
   $Game::Running = true;
   
   loadCustomDecals(); // Added

Now, add variable customDecal = true; in the projectile of the weapons you want to be affected by the custom decals , this is good for RocketLaunchers which usually have the same decal unregardless of material.

To test:
Run game,
Load level,
Load up an random shape,
Find the material name of the shape and enter material.setCustomDecal(decal); in the console, where material is the name/id of the material, and decal is the name/id of the decal.
And try shooting it.

The only issue I would like to get fixed is to avoid the requirement for having an extra .cs file for loading the custom materials. The problem here is that i cannot put the customDecal = BulletDecalsAll; variable inside a material definition, because the decal has to be loaded to be able to assign it, and trying to load a decal before the material is theoretically impossible since decals are depending on materials damn you evil circle. If anyone have the fix for this it would be greatly appreciated!

If you stumble upon some issues, let me know.
Also know that my methods might not be correct, nor the most professional. Therefore if you see some silly mistakes please leave a comment with the "fix".

Other resources in my Weapon Mod:
1. MXG Weapon Mod - Decals Depending on Material
2. MXG Weapon Mod - Explosion and SFX Depending on Material
3. MXG Weapon Mod - Structure and Armor Piercing Projectiles
4. MXG Weapon Mod - Advanced Crosshair


Thanks,
Marcus L.

#1
05/02/2010 (2:37 pm)
Awesome first resource, Marcus! This will be very helpful - thank you!
#2
05/02/2010 (3:58 pm)
i second that, this is a necessary or "must be" resource for T3D...
#3
05/02/2010 (7:32 pm)
this is great work Marcus, this will come in very handy
#4
05/03/2010 (7:08 am)
Thanks for your supportive responses guys!

I see you figured this is my first resource Konrad, forgot to mention that ;).
#5
05/03/2010 (9:13 am)
Nice work Marcus! Was just lamenting the general purpose projectile decal the other day and how to overcome it.... very timely resource, thanks

Also gives an idea to go a step further and add varying impact/hit (ricochet) sounds depending on material (instead of random)
- something that's been in the back of my mind for a while now.
#6
05/03/2010 (4:16 pm)
Really nice resource! Thanks Marcus, its an essential feature that should be added to the engine by default. :-)
#7
05/04/2010 (7:15 pm)
Nice Marcus! T3D could really use this.

Michael Hall
Quote:
Also gives an idea to go a step further and add varying impact/hit (ricochet) sounds

Not only that, but perhaps could even be tweaked for penetrable objects such as plywood!

#8
05/05/2010 (1:17 am)
@ Michael Hall & Travis Evans

If you read here:
Quote:
Last, i will probably add another resource regarding different sound or particle effects depending on material soon.
I am going to release customized versions of this resource for both different sound effects and and particle effects.
And, good idea Travis, bout that penetrating function. Will try to implement that.
And good to see your back Michael.
#9
05/13/2010 (6:26 am)
BUG FIX:

For those who have/have tried to install this resource, there is one bug fix, and there was a piece of missing code:

Bug, T3D/projectile.cpp:
...
//In Projectile::unpackUpdate(NetConnection* con, BitStream* stream)
          stream->read( &mCollideHitType );
          DecalData* decal = NULL; // BUG, Change this line

          explode(explodePoint, explodeNormal, decal, mCollideHitType);

Missing code, materials/materialDefinition.h:
...
   virtual bool isAutoGenerated() const { return mAutoGenerated; }
   virtual void setAutoGenerated(bool isAutoGenerated) { mAutoGenerated = isAutoGenerated; }
   virtual void setCustomDecal(DecalData *decal); // Added

Edited resource with the fixes.
#10
09/11/2011 (11:52 pm)
this is the exact thing im lookin for so i put it into a fresh install of the latest engine. compiles fine...no errors....placed customdecal=true in the soldier gun but no matter what i do no decals will show up. i know the matid is correct so i must just be spacing something off? any ideas? thanks for the great resource!
#11
09/12/2011 (3:25 am)
Hi Brent,
I haven't touched torque in a while now, so I haven't been able to update this resource. However I can update and fix potential bug (I was not an advanced C++ user at the time i wrote this resource :P) if you'd want me to.