Game Development Community

Resolved]Mounting Images on RTS units?

by Johnathan Moore · in RTS Starter Kit · 02/25/2006 (11:57 am) · 10 replies

Hi,
I want to mount objects onto the RTS units but at the moment i dont think it works, I read somewhere it
was disabled because of all the different networking

does anyone know about reactivating it?

#1
02/27/2006 (7:25 am)
Ok for anyone who needs this aswell I plan to make a lite version of the shapebase image without any of the state/light/trigger code and then network it, anyone think this is a good idea?, my c++ is a bit rusty
#2
03/01/2006 (1:01 pm)
Sorry John, been relying on a feed for posts, missed this one! I will check into the RTSUnit class to see what it would need if anything, to support mounted objects.
#3
03/01/2006 (1:06 pm)
It looks like, since it inherits player.h, mounting objects should work fine. I will try it out tomorrow AM and see..

Whoops! I misspoke. I did not notice that RTSUnit had its own PackUpdate/UnpackUpdate.

Look at the doc here: tdn.garagegames.com/wiki/RTS/RTSUnit at the Packet Updates Section and it talks about the removal of the code, and where to look to get it in again ;)
#4
03/01/2006 (1:13 pm)
Ok thanks
#5
03/02/2006 (7:09 pm)
John- This worked out pretty well.

in rtsunit.cc, there are 3 changes:

1) around line 1001, in PackUpdate, find:

if(!stream->writeFlag(mask & (DamageMask | SoundMask | ThreadMask | SkinMask |
      ActionMask | AIMask | InitialUpdateMask | CloakMask | ImpactMask | 
      MoveMask | ModifierMask | ProjectileMask)))
      return retMask;

and change it to:

if(!stream->writeFlag(mask & (DamageMask | SoundMask | ThreadMask | SkinMask |
      ActionMask | AIMask | InitialUpdateMask | CloakMask | MountedMask | ImpactMask | 
      MoveMask | ModifierMask | ProjectileMask)))
      return retMask;

2) right above:
if(stream->writeFlag(mask & SkinMask))
      con->packStringHandleU(stream,mSkinNameHandle);

add:
if (stream->writeFlag(mask & ImageMask)) {
      for (int i = 0; i < MaxMountedImages; i++)
         if (stream->writeFlag(mask & (ImageMaskN << i))) {
            MountedImage& image = mMountedImageList[i];
            if (stream->writeFlag(image.dataBlock))
               stream->writeInt(image.dataBlock->getId() - DataBlockObjectIdFirst,
                                DataBlockObjectIdBitSize);
            con->packStringHandleU(stream, image.skinNameHandle);
            stream->writeFlag(image.wet);
            stream->writeFlag(image.ammo);
            stream->writeFlag(image.loaded);
            stream->writeFlag(image.target);
            stream->writeFlag(image.triggerDown);
            stream->writeInt(image.fireCount,3);
            if (mask & InitialUpdateMask)
               stream->writeFlag(isImageFiring(i));
         }
   }

3) and right before the end packUpdate, add:
if (mask & MountedMask) {
      if (mMount.object) {
         S32 gIndex = con->getGhostIndex(mMount.object);
         if (stream->writeFlag(gIndex != -1)) {
            stream->writeFlag(true);
            stream->writeInt(gIndex,NetConnection::GhostIdBitSize);
            stream->writeInt(mMount.node,ShapeBaseData::NumMountPointBits);
         }
         else
            // Will have to try again later
            retMask |= MountedMask;
      }
      else
         // Unmount if this isn't the initial packet
         if (stream->writeFlag(!(mask & InitialUpdateMask)))
            stream->writeFlag(false);
   }
   else
      stream->writeFlag(false);
   return retMask;


Any flags we write in packUpdate, we have to read in unpackUpdate.
in unpackUpdate:

1) Right before:
if (stream->readFlag())  // SkinMask
   {
      StringHandle skinDesiredNameHandle = con->unpackStringHandleU(stream);
      if (mSkinNameHandle != skinDesiredNameHandle)
      {
         mSkinNameHandle = skinDesiredNameHandle;
         if (mShapeInstance)
         {
            mShapeInstance->reSkin(mSkinNameHandle);
            if (mSkinNameHandle.isValidString())
               mSkinHash = _StringTable::hashString(mSkinNameHandle.getString());
         }
      }
   }

add:
if (stream->readFlag()) {
      for (int i = 0; i < MaxMountedImages; i++) {
         if (stream->readFlag()) {
            MountedImage& image = mMountedImageList[i];
            ShapeBaseImageData* imageData = 0;
            if (stream->readFlag()) {
               SimObjectId id = stream->readInt(DataBlockObjectIdBitSize) +
                  DataBlockObjectIdFirst;
               if (!Sim::findObject(id,imageData)) {
                  con->setLastError("Invalid packet (mounted images).");
                  return;
               }
            }

            StringHandle skinDesiredNameHandle = con->unpackStringHandleU(stream);

            image.wet = stream->readFlag();

            image.ammo = stream->readFlag();

            image.loaded = stream->readFlag();

            image.target = stream->readFlag();

            image.triggerDown = stream->readFlag();

            int count = stream->readInt(3);

            if ((image.dataBlock != imageData) || (image.skinNameHandle != skinDesiredNameHandle)) {

               setImage(i, imageData, skinDesiredNameHandle, image.loaded, image.ammo, image.triggerDown);

            }

            if (isProperlyAdded()) {
               // Normal processing
               if (count != image.fireCount)
               {
                  image.fireCount = count;
                  setImageState(i,getImageFireState(i),true);

                  if( imageData && imageData->lightType == ShapeBaseImageData::WeaponFireLight )
                  {
                     mLightTime = Sim::getCurrentTime();
                  }
               }
               updateImageState(i,0);
            }
            else
            {
               bool firing = stream->readFlag();
               if(imageData)
               {
                  // Initial state
                  image.fireCount = count;
                  if (firing)
                     setImageState(i,getImageFireState(i),true);
               }
            }
         }
      }
   }


2) Right before the end of the function, add:
if (stream->readFlag()) {
      if (stream->readFlag()) {
         S32 gIndex = stream->readInt(NetConnection::GhostIdBitSize);
         ShapeBase* obj = dynamic_cast<ShapeBase*>(con->resolveGhost(gIndex));
         S32 node = stream->readInt(ShapeBaseData::NumMountPointBits);
         if(!obj)
         {
            con->setLastError("Invalid packet from server.");
            return;
         }
         obj->mountObject(this,node);
      }
      else
         unmount();
   }

Compile!

Now you can script a mount in the standard fashion. I threw one into player.cs->RTSUnitData::onAdd of
%obj.mountImage(CrossbowImage,0);

To get this:

www.brooklawnstudios.com/images/rtsmounted.jpg
#6
03/04/2006 (6:15 am)
Wow thanks for going to that trouble, ill add that in now
#7
03/08/2006 (3:48 pm)
So this can add objects e.g. weapons to units ??????
#8
03/08/2006 (6:18 pm)
Yep! Take a look at the pic.
#9
02/07/2010 (4:14 am)
Works great, but it does generate an error on the inventory since its not used for rts game.

I just disabled it as follows, works fine (weapon.cs);
function WeaponImage::onMount(%this,%obj,%slot)
{
   // Images assume a false ammo state on load.  We need to
   // set the state according to the current inventory.
   /*
   if (%obj.getInventory(%this.ammo))
      %obj.setImageAmmo(%slot,true); 
      */
#10
02/07/2010 (4:39 am)
I dont understand how -- but somehow, after I mount an image ... now the units can no longer move. Will test it out some more ... or possibly just find a way to add weapons to units and re-export the models with weapons included.

EDIT: Found the solution. I was mounting it on Player::onAdd() and units were then unable to move afterwards. I moved the call to RTSUnitData::onAdd() and now works great!!

// Check to see if this should have a projectile, so look at the datablock
   if ((%objClassName $= "RTSUnit") && (%this.isMelee == false))
      {
         %obj.setProjectileDatablock(CrossbowProjectile);         
         %obj.mountImage(BowImage,0);
      }