Game Development Community

Unit Attack Accuracy

by Daniel Rank · in RTS Starter Kit · 11/21/2004 (11:09 am) · 3 replies

I wanted to add an accuracy field for the RTS units so that they wouldn't always hit the target. I'm not very familiar with Torque yet, so this probably isn't the best implementation, and I would appreciate any suggestions.

In RTSUnit.h I added an accuracy data field, a random number generator and seed.
class RTSUnitData : public PlayerData
{
. . .
public:
   S32 mAccuracy;
. . .
}

class RTSUnit : public Player
{
. . .
private:
. . .
   S32 mTimeSeed;
   MRandom mRandom;
. . .

public:
. . .
   S32 getTimeSeed();
   S32 getRandomInt(S32 i, S32 n);
. . .
}

The following code was added to RTSUnit.cc.
For the accuracy data field:
RTSUnitData::RTSUnitData()
{
   mAccuracy = 5;
. . .
}

void RTSUnitData::packData(BitStream* stream)
{
. . .
   stream->write(mAccuracy);
. . .
}

void RTSUnitData::unpackData(BitStream* stream)
{
. . .
   stream->read(&mAccuracy);
. . .
}

void RTSUnitData::initPersistFields()
{
. . .
   addField("accuracy", TypeS32, Offset(mAccuracy, RTSUnitData));
. . .
}

For the RNG:
RTSUnit::RTSUnit()
{
. . .
   mTimeSeed = 0;
}

S32 RTSUnit::getTimeSeed() { return mTimeSeed; }

// kludge
S32 RTSUnit::getRandomInt(S32 i, S32 n)
{
  mRandom.setSeed(mTimeSeed);
  mTimeSeed += mRandom.randI(0, 10000);
  mRandom.setSeed(mTimeSeed);
  return mRandom.randI(i, n);
}

void RTSUnit::processTick(const Move *move)
{
   // kludge
   mTimeSeed += 3333;
. . .
}

// for debugging
ConsoleMethod( RTSUnit, getTimeSeed, S32, 2, 2, "()")
{
   return object->getTimeSeed();
}

ConsoleMethod( RTSUnit, getRandomInt, S32, 4, 4, "(S32 i, S32 n)")
{
   return object->getRandomInt(dAtoi(argv[2]), dAtoi(argv[3]));
}

Then I tested it out with rifleman.cs by adding to riflemanBlock::onAttack.
function riflemanBlock::onAttack(%this, %attacker, %target)
{
   echo(attacking);
   %hitAccuracy = %attacker.getRandomInt(1, 10);
   echo(%hitAccuracy);
   echo(%attacker.getTimeSeed());

   if(%hitAccuracy <= %attacker.getDataBlock().accuracy)
   {
      echo(hit);
      %damage = %attacker.getDataBlock().baseDamage;
      if(%attacker.getNetModifier().baseDamage)
         %damage *= %attacker.getNetModifier().baseDamage;

      %armor  = %target.getDataBlock().armor;
      if(%target.getNetModifier().armor)
         %armor *= %target.getNetModifier().armor;
		  
      if(%damage > %armor)
         %damage -= %armor;
      else
         %damage = 0;

      %target.applyDamage(%damage);
   }
   else
   {
      echo(miss);
   }
}

So for this implementation the accuracy field should be set to an int between 1 and 10. Again, I'm looking for suggestions and better implementations. I would also like to find out how to prevent the target unit from "glowing" when attacked, when the attacker misses. I would appreciate any help on this, or else I will post my own findings later.

About the author

Recent Threads


#1
11/21/2004 (11:20 am)
This is going to cause you a problem I think, due to the fact that the starter kit "out of the box" I think only simulates the attack client side, while performing the attack server side, and then simply dumping the damage down the pipe (inet, local, internal to the process if playing single player, whatever).

What this means is that your client is going to go ahead and do it's own "pretend" attacks regardless of what happens server side (hence the glowing of a hit), while the server is going to only update the damage on the unit when a real hit connects.

I don't have an implementation fix for you right off the bat, but this is yet another thing our project will have to address, so I'll start thinking about it.

Of course, my understanding of the documentation could be comepletely wrong as well!
#2
11/22/2004 (12:25 pm)
I've not started to code it up yet - but here is my approach. At the moment I think the aim defaults to shooting at the target unit's feet. What I'm going to do is create a box around the target and pick a position randomly within that box. Some might be a hit others might be a miss. Of course the bigger the box, the less accuracy. For the game I am designing this works well, because if you miss and hit another unit - thats fine - its 'realistic'. And you can do this all in script.

EDIT: My idea above is complete rubbish. I ought to look at the code before shooting my mouth off. Opps.
#3
01/17/2006 (9:18 pm)
Do you have any problem with the code? I have made the changes, but when I try to launch the mission, appears an error "out of range" from the bitStream class.