Wednesday, July 9, 2014

This why you should code Custom primitive classes

Let say that in an Action game,

the player has start 10 MaxHP.
this value shall not go below 0, and will not rise beyond 999.
the value for HP itself, will not go outside MaxHP range.

When an enemy deal damage to the Player, you will have a need to clamp it

public void DealDamage( int damage )
{
 hp -= damage;
 if( hp <= 0 ) hp = 0;
 if( hp >= maxHP ) hp = maxHP
}

simple right?

but what if the hp is use for other things as well.

Healing is effectively Dealdamage with negative value,
but sometime you shouldn't use negative value due to number confusion

public void HealUnit( int amount )
{
 hp += amount;
 if( hp <= 0 ) hp = 0;
 if( hp >= maxHP ) hp = maxHP
}

or anything that could adjust maxHP,

public void AdjustMaxHP( int amount )
{
  maxHP += amount;
  if( maxHP <= 0 ) maxHP = 1;
   if( maxHP > 999 ) maxHP = 999;

 if( hp <= 0 ) hp = 0;
 if( hp >= maxHP ) hp = maxHP;
}

You could see the pattern now.

---------------------

The problem is,
If you have to add Clamping scripts to all of them,
Not only is this very tedious,
Eventually someone will miss one of them and it will cause logic error.

---------------------

Something like this will help by a bit, but it still doesn't solve long term issue.

public void DealDamage( int damage )
{
 hp -= damage;
 ClampHP();
}

public void HealUnit( int amount )
{
 hp += amount;
 ClampHP();
}

public void AdjustMaxHP( int amount )
{
  maxHP += amount;
 ClampHP();
}

void ClampHP()
{
   if( maxHP <= 0 ) maxHP = 1;   if( maxHP > 999 ) maxHP = 999;

 if( hp <= 0 ) hp = 0;
 if( hp >= maxHP ) hp = maxHP;
}

---------------------

So, how do we fix this?

Simple enough, make HP and something familiar its own class

public class Custom_Int
{
 protected int val;
 protected int val_Min;
 protected int val_Max;

 public Custom_Int()
{
  val_Min = 0;
 val_Max = 10;
 val = val_Max;
}

public int GetVal() { return val; }

public void AdjustVal( int num )
{
  val += num;
  ClampVal();
}

public void AdjustValMax( int num )
{
  val_Max += num;
  ClampValMax();
}

void ClampVal()
{
 if( val <= val_Min )
  {
   val = val_Min;
   return;
  }
 if( val >= val_Max ) val = valMax;
}

void ClampValMax()
{
   if( val_Max <= val_Min ) valMax = val_Min+1;
   if( val_Max > 999 ) valMax = 999;
   ClampVal();
}

}

---------------

Back to the main Code, all you have to do is these;

Custom_Int hp = new Custom_Int();

public void DealDamage( int damage )
{
  hp.AdjustVal(-damage);
}

public void HealUnit( int amount )
{
   hp.AdjustVal(amount);
}

public void AdjustMaxHP( int amount )
{
  hp.AdjustValMax(amount);
}

Much cleaner isn't it?

-------------------

Also, you could make inherited class in case you want something specific to that Parameter

public class HP : Custom_Int()
{
  int fatigueDamage = 0;
 int  fatigueMaxHP;

 public void DealFatigueDamage( int damage )
  {
    fatigueDamage += damage;
    fatigueMaxHP = val_Max - fatigueDamage;
    ClampVal();
  }

   public override void ClampVal()
   {
   if( fatigueMaxHP < val_Min ) fatigueMaxHP = val_Min+1;

   if( val <= val_Min )
    {
     val = val_Min;
     return;
    }
   if( val > val_fatigueMaxHP ) val = fatigueMaxHP ;
  }}