Friday, June 15, 2012

Platformer Kit: SPG_HealthPickup class (UnrealScript)



The SPG_HealthPickup class is used to represent a health item that can be dropped from an enemy when he dies. This class is a subclass of DroppedPickup. Its variables are:
class SPG_HealthPickup extends DroppedPickup
      placeable;

// Static mesh used by the pick up
var(HealthPickup) const StaticMeshComponent Mesh;

// Sound to play when the pick up is picked up by a pawn
var(HealthPickup) const SoundCue PickupSound;

// How much health to give to the pawn when picked up
var(HealthPickup) const int HealthToGive;

The Platformer Starter Kit also uses an Archetype of this class to ease changes in the values ​​of its variables.

The image below shows the default values ​​of the Archetype of the SPG_HealthPickup class.


If you know nothing about Pickups, I recommend reading my article "PickupFactory and Inventory in UnrealScript".

The "GiveTo(Pawn P)" function is called when the player gets an item. It just plays a sound and gives more health to the player:
function GiveTo(Pawn P)
{
    // Play sound
    if (PickupSound != None)
    {
        PlaySound(PickupSound);        
    }

    // Add health to the player, but clamp it to the pawn's maximum health
    P.Health = Min(P.Health + HealthToGive, P.HealthMax);

    // Handle the rest of pick up
    PickedUpBy(P);
}

The "int Min(int A, int B)" function returns the smallest number between two integers and is used to prevent the player's health exceeds the maximum value. The "PickedUpBy(Pawn P)" function belongs to the DroppedPickup class and it just calls the "Destroy()" function to remove this Pickup from the game.

The SPG_HealthPickup class overrides the "ValidTouch(Pawn Other)" function, which is within the state "Pickup" of the DroppedPickup class, with a simpler version of the function. This function is called every time there is a collision with an object of type Pawn to check if it is the player who is picking up the item.
auto state Pickup
{
    function bool ValidTouch(Pawn Other)
    {
        // make sure its a live player
        if (Other == None || !Other.bCanPickupInventory || (Other.DrivenVehicle == None && Other.Controller == None))
        {
            return false;
        }

        // make sure thrower doesn't run over own weapon
        if (Physics == PHYS_Falling && Other == Instigator && Velocity.Z > 0)
        {
            return false;
        }

        return true;
    }
}

Finally, we have the defaultproperties block whose code is below. It defined an object of StaticMeshComponent type with the name MyStaticMeshComponent. If you look at the image of the Archetype that was created for this class, the Mesh property  is associated with the MyStaticMeshComponent object that will be used as a component, using ":" and the name of the object.
defaultproperties
{
    // Remove the sprite component
    Components.Remove(Sprite);

    // Add the static mesh component
    Begin Object Class=StaticMeshComponent Name=MyStaticMeshComponent
    End Object
    Mesh=MyStaticMeshComponent
    Components.Add(MyStaticMeshComponent);
}