Help with reload system

Hello guys, it`s me again. Sorry for always asking, however I am still learning Unreal Scripting and I like to get help from more experienced users here.

I am creating a weapon reload system, I have seen many tutorials on old epic games forums, and on youtube, however many of these tutorials are incomplete, so I had to fix many things (i got pieces from here and there). It`s almost working perfectly, I even changed the HUD in flash/scaleform to show the current bullets equiped on the gun and the total ammo the player has avaiable.

I will try to summarize what I did and what are my doubts.

Here is my weapon reload class:


######################################################
class WeaponReload extends UTWeapon;

//these variables are for handle the ammo quantity in the magazine
var int MaxMagAmmo, TransferAmmo;
var bool bIsReloading;

//reload function to play reload animation///////////////////////
exec function Reload() {

  //this statement will prevent weapon reloading when ammo is full
  if (AmmoTotal > 0 && !bIsReloading && AmmoCount < MaxAmmoCount) {
    ForceEndFire();
    bIsReloading = true;     
    PlayWeaponAnimation('WeaponReload', 1.9);
    WeaponPlaySound(WeaponEquipSnd);
    setTimer(1.9, false, 'AddAmmoToMag');
  }

}
//reload function to play reload animation///////////////////////

//function Add Ammo To Magazine///////////////////
function AddAmmoToMag(){

  //if AmmoTotal > 0//
  if (AmmoTotal > 0) {

    TransferAmmo = MaxMagAmmo - AmmoCount;

    //if AmmoTotal >= TransferAmmo//
      if (AmmoTotal >= TransferAmmo) {

    //this will add the transfer ammo to the current ammo count
      AmmoCount = AmmoCount + TransferAmmo;

    //this will reduce from the ammo total the ammo which was transfered to the magazine
      AmmoTotal = AmmoTotal - TransferAmmo;

       }

    //if ammototal < TransferAmmo
      else{

      AmmoCount = AmmoCount + AmmoTotal;
      AmmoTotal = AmmoTotal - AmmoTotal;

      }
      //if AmmoTotal >= TransferAmmo//

      bIsReloading = false;
      ClearTimer();

  }     
  //if AmmoTotal > 0//

}
//function Add Ammo To Magazine///////////////////

//function to check if player is allowed to shoot///////////////               
simulated function StartFire(byte FireModeNum) 
{

  if (bIsReloading) {
  return;
  }

  Super.StartFire(FireModeNum);

}
//function to check if player is allowed to shoot///////////////       
######################################################


This is my custom weapon class:



######################################################
class UTWeap_Enforcer extends WeaponReload;

defaultproperties
{

//The maximum amount of ammo the magazine clip can hold
MaxMagAmmo=25

//The current ammo count
AmmoCount=5

//The initial ammo count for this weapon if picked up from a weapon locker
LockerAmmoCount=5

//The maximum amount of ammo this weapon can hold
MaxAmmoCount=25

//We need to set an initial value for the reload function work and it must be the double of max ammo (it is extra ammo)
AmmoTotal=50
MaxAmmoTotalCount=100

    //visual properties///////////////////////////////
    PlayerViewOffset=(X=-1.0,Y=0.0,Z=3.0)
    //x -> distance from camera
    //y -> horizontal position
    //z -> vertical position

    Begin Object class=AnimNodeSequence Name=MeshSequenceA
        bCauseActorAnimEnd=true
    End Object

    Begin Object Name=FirstPersonMesh
        SkeletalMesh=SkeletalMesh'WP_Enforcers.Mesh.SK_WP_Enforcers_1P_fbx'
        FOV=60
        Animations=MeshSequenceA
        AnimSets(0)=AnimSet'WP_Enforcers.Anims.K_WP_Enforcers_1P_Base'
        bForceUpdateAttachmentsInTick=True
        Scale=0.9000000
    End Object

    Begin Object Name=PickupMesh
        SkeletalMesh=SkeletalMesh'WP_Enforcers.Mesh.SK_WP_Enforcer_3P_Mid_fbx'
        Scale=0.9000000
    End Object

    ArmsAnimSet=AnimSet'WP_Enforcers.Anims.K_WP_Enforcers_1P_Arms'

    PivotTranslation=(Y=0.0)

    //this controls the projectile spawn position
    FireOffset=(X=0,Y=5,Z=-5)
    //x -> distance from camera
    //y -> horizontal position (negative value moves to left)
    //z -> vertical position    

    //visual properties///////////////////////////////

    //weapons in udk ultimate are ballistic, i.e, they trully shoot real bullets, projectiles which are controlled by physics properties
    //here the properties of the bullet are controlled by the class UTProj_Enforcer
    WeaponFireTypes(0)=EWFT_Projectile
    WeaponProjectiles(0)=class'UTProj_Enforcer'

    //sounds
    WeaponEquipSnd=SoundCue'WP_Enforcers.Sounds.A_Weapon_Enforcer_ReloadComposite01_Cue'
    WeaponPutDownSnd=SoundCue'WP_Enforcers.Sounds.A_Weapon_Enforcer_Lower01_Cue'
    WeaponFireSnd(0)=SoundCue'WP_Enforcers.Sounds.Enforcer_Fire_Bullet_cue'
    //PickupSound=SoundCue'WP_Enforcers.Sounds.A_Weapon_Enforcer_ReloadComposite01_Cue'

    //muzzleflash
    MuzzleFlashSocket=MuzzleFlashSocket
    MuzzleFlashPSCTemplate=ParticleSystem'WP_Enforcers.Effects.P_WP_Enforcers_MuzzleFlash_fix'

    //ammo fire speed functions///////////////////////////////
    FireInterval(0)=0.35
    FireInterval(1)=0.35
    //ammo fire speed functions///////////////////////////////

    //CrosshairImage=Copy texture from Content Browser
    CrossHairCoordinates=(U=128,V=0,UL=64,VL=64)

    //<DO NOT MODIFY>
    Mesh=FirstPersonMesh
    DroppedPickupMesh=PickupMesh
    PickupFactoryMesh=PickupMesh
    AttachmentClass=Class'UTAttachment_Enforcer'

//custom zoom properties to simulate iron sights effect    
DefaultProperties
{

bZoomedFireMode(0)=0
bZoomedFireMode(1)=1

ZoomedTargetFOV=35.0
ZoomedRate=9000
}
//custom zoom properties to simulate iron sights effect    

}
######################################################


Here is my ammo class



######################################################
/**
* Created using Unreal Script Wizard by RyanJon2040
* Visit: www.dynamiceffects.net
* Meet me on Facebook: www.facebook.com/satheeshpv
*/

class UTAmmo_Enforcer extends UTAmmoPickupFactory;

DefaultProperties
{

    Begin Object Name=AmmoMeshComp
        StaticMesh=StaticMesh'WP_Enforcers.Mesh.S_Ammo_Enforcer_fbx'
        Translation=(X=0.0,Y=0.0,Z=-16.0)
    End Object

    Begin Object Name=CollisionCylinder
        CollisionHeight=14.4
    End Object

    AmmoAmount=0

    //custom reload variable
    AmmoTotalAmount=5

    Drawscale=0.5

    PickupSound=SoundCue'WP_Enforcers.Sounds.A_Weapon_Enforcer_ReloadComposite01_Cue'

    //<DO NOT MODIFY>
    TargetWeapon=Class'UTWeap_Enforcer'
}

######################################################


Here are some changes I made in UTWeapon

I added these 2 custom variables to control the total ammo the player can carry (that will be transfered to gun magazine when reload)

//custom variable for weapon reload system
var int AmmoTotal;
var int MaxAmmoTotalCount;

Then I changed the function AddAmmo to add ammo for the variable ammototal, so the player wll manually transfer ammo for the ammocount of weapon. It means that collecting ammo will not add ammocount, instead, will add ammo total, so the player when reloading the gun will manually transfer from Ammototal to Ammocount (gun magazine, the current ammo which is equiped in the gun):



//add ammototal for reloading system//
function int AddAmmo( int Amount )
{

    //custom reload add ammo count
    AmmoTotal = Clamp(AmmoTotal + Amount,0,MaxAmmoTotalCount);

    // check for infinite ammo
    if (AmmoTotal <= 0 && (UTInventoryManager(InvManager) == None || UTInventoryManager(InvManager).bInfiniteAmmo))
    {
        AmmoTotal = MaxAmmoTotalCount;
    }    

    //custom reload variable
    return AmmoTotal;

}
//add ammototal for reloading system//


However when I have done this, the ammocount was not being reduced when the player shoots, so I changed the original AddAmmo function to this:



//original add ammo function
function int AddAmmoDefault( int Amount )
{   
    //default add ammo count
    AmmoCount = Clamp(AmmoCount + Amount,0,MaxAmmoCount);

    // check for infinite ammo
    if (AmmoCount <= 0 && (UTInventoryManager(InvManager) == None || UTInventoryManager(InvManager).bInfiniteAmmo))
    {
        AmmoCount = MaxAmmoCount;
    }

    return AmmoCount;
}
//original add ammo function


And changed the function ConsumeAmmo to:



/**
 * Consumes some of the ammo
 */
function ConsumeAmmo( byte FireModeNum )
{
    // Subtract the Ammo
    AddAmmoDefault(-ShotCost[FireModeNum]);
}


Then I also changed this function in the UTAmmoPickupFactory:



class UTAmmoPickupFactory extends UTItemPickupFactory
    ClassGroup(Pickups,Ammo)
    abstract;

/** The amount of ammo to give */
var int AmmoAmount;

//custom variable for reload system
var int AmmoTotalAmount;

/** The class of the weapon this ammo is for. */
var class<UTWeapon> TargetWeapon;

function SpawnCopyFor( Pawn Recipient )
{
    if ( UTInventoryManager(Recipient.InvManager) != none )
    {    
        //default add ammo to weapon
        //UTInventoryManager(Recipient.InvManager).AddAmmoToWeapon(AmmoAmount, TargetWeapon);

        //custom reload system add ammototal to weapon
        UTInventoryManager(Recipient.InvManager).AddAmmoToWeapon(AmmoTotalAmount, TargetWeapon);
    }



And last thing I modified the NeedsAmmo function from UTInventoryManager to don’t allow the player to collect the AmmoTotal more than the limit MaxAmmoTotalCount:



function bool NeedsAmmo(class<UTWeapon> TestWeapon)
{
    local array<UTWeapon> WeaponList;
    local int i;

    // Check the list of weapons
    GetWeaponList(WeaponList);
    for (i=0;i<WeaponList.Length;i++)
    {
        if ( ClassIsChildOf(WeaponList*.Class, TestWeapon) )    // The Pawn has this weapon
        {
            //if ( WeaponList*.AmmoCount < WeaponList*.MaxAmmoCount )

            //this will allow pickup ammo even if the ammocount is full
            if ( WeaponList*.AmmoTotal < WeaponList*.MaxAmmoTotalCount )
                return true;

            else
                return false;

        }
    }


I also created a new dynamic textfield in Flash for showing AmmoTotal variable and declared this variable in GFxMinimapHud



        i = Weapon.GetAmmoCount();
        if (i != LastAmmoCount)
        {
            LastAmmoCount = i;

            AmmoCountTF.SetText(i);

            //custom variable reload system
            AmmoTotalCountTF.SetText(Weapon.AmmoTotal);


The only problem I am having now is that the Ammototal count only updates after I shoot or after I reload. It works fine. I collect ammo, and this ammo I collect does not increase the AmmoCount for the gun, rather it increases the Ammototal, then when I reload, it transfer the bullets from AmmoTotal to AmmoCount, just like it needs to be. Then it reduces from the Ammototal the ammount which was transfered for the gun clip (AmmoCount). However the AmmoTotal count only updates when I reload or shoot. It does not update when I Collect ammo (pickup ammo event).

Any tips?

Last but not least, how can I remove the function of UTGame which automatically changes to next gun when the ammo is empty and avoids the player to select a weapon which is empty of Ammo. I want the player to manually reload the weapon when ammo is zero, however, UDK auto changes for next weapon and avoid me selecting a gun with zero ammo.

Sorry for the long post.

:slight_smile:

Hello guys, I already found how to avoid automatically swithing to next weapon when ammo gets empty.

I just commented some lines on the simulated function WeaponEmpty() in UTWeapon:


/**
* Called when the weapon runs out of ammo during firing
*/
simulated function WeaponEmpty()
{
// If we were firing, stop
if ( IsFiring() )
{
GotoState('Active');
}

if ( Instigator != none && Instigator.IsLocallyControlled() )
{
//Instigator.InvManager.SwitchToBestWeapon( true );

}
}

However I still could not find a way to update the display of the ammototal count when collecting new ammo, the display count just updates after I shoot or after I reload, however the number count does not update when I collect new ammo, even though the ammocount gets increased, however it only does not show.

In example, if I have the ammototal count as 10, then I collect more 5 ammo units, it goes to 15, however the display only shows 10 untill I eitheir reload, or shoot one shoot.

Any help?

Other problem now, is that althought now UDK does not change to next weapon whenever the current ammo count is zero, still I have a problem is when my weapon is with empty ammo, then I manually change to other weapon, I can`t select again my weapon, because UDK does not allow select a weapon with empty ammo.

Please help me guys.

Sorry man, I can help in this, I did my own weapon class, tired of the engine class complexity. At the end, you only need to use attachtosocket, setbase and play animations in complete and half body.

I have found something in UTInventoryManager Class, the function “simulated function SwitchWeapon(byte NewGroup)”

I found this line:


    if ( WeaponList[NewIndex].HasAnyAmmo() )
    {
        SetCurrentWeapon(WeaponList[NewIndex]);
    }

So I changed to:



    if ( WeaponList[NewIndex].HasAnyAmmo() == true )
    {
        SetCurrentWeapon(WeaponList[NewIndex]);
    }

    if ( WeaponList[NewIndex].HasAnyAmmo() == false )
    {
        SetCurrentWeapon(WeaponList[NewIndex]);
    }    

However, it did not work, I already was able to make UDK dont change to next weapon whenever the current ammo count is zero, however, now I have a problem is when my weapon is with empty ammo, then I manually change to other weapon, I cant reselect again my weapon, because UDK does not allow select a weapon with empty ammo.

I did search through all classes for any reference to empty ammo, switch weapon, and so on (I am using Notepad ++ search in files function), however I only found the above function from UTInventoryManager.

Why Unreal Scripting is not well documented? UDN topics are very vague, and they don`t explain in clear terms for noobs or begineers.

Any ideas?

My guns require reload. My guns don’t autoswitch on empty. I’m extending from UT
Your ammocount problem something to do with your HUD updating? For me updating the ammocount was relatively straightforward… (I don’t mean it was easy to discover how :slight_smile: )



function ConsumeAmmo( byte FireModeNum )
{
   // Subtract the Ammo from the Magazine
   if(MagazineAmmoCount >= ShotCost[FireModeNum])
   {
      MagazineAmmoCount -= ShotCost[FireModeNum];
    AddAmmo(-ShotCost[FireModeNum]);
   }
}

simulated function WeaponEmpty()
{
    // If we were firing, stop
    if ( IsFiring() )
    {
        bCanThrow = true;
        ClearTimer();
        GotoState('Active');   <- sends the weapon back to Active and therefore idle.  Your code is similar.
    }
}


@Snipe34

Hello my friend. Yeah, I think is something with the HUD display which is not updating only when I collect ammo. Like I said, I changed things a bit from standard UT Code, in the sense that collecting Ammo (ammo pickup) doesn`t increase the gun ammocount, it increases my new variable which is AmmoTotalCount. So the gun is empty, then whenever the player reloads, the “bullets”, the ammo quantity is transfered from AmmoTotal to AmmoCount (the ammo which is loaded in the gun and ready to fire, i.e, the bullets).

Whenever the player reloads, the HUD which shows AmmoTotal updates normally. Whenever I collect ammo, it increases the AmmoTotal (my new variable), however, the display does not update the correct number, the number only updates whenever I shoot or whenever I reload.

Anyway guys, thanks for the info and tips. I will try a new approach now for developing my game. As I am developing and at the same time learning unreal script, whenever I stuck on something and can`t find the solution, I will register this as a “bug” and go on on developing my game, so later in the project, whenever I acquire more knowledge, I can come back and fix these “bugs”.

I think this approach will help me to continue on developing my game, instead of stucking on something and then getting frustated :frowning:

Anyway.

Cheers :smiley:

Follow thru the MagazineAmmoCountMax and MagazineAmmoCount
"GetAmmoCount"and “MaxAmmoCount” are already in my code due to extending from UTWeapon



extends GFxMinimapHud

    Weapon = UTWeapon(KTP.Weapon);
    if (Weapon != none)// && UTV == none)
    {
        if (Weapon != LastWeapon)
        {
            AmmoCountTF.SetText("");
            i = (Weapon.MaxAmmoCount);
            LastWeapon = Weapon;
        }
        i = Weapon.GetAmmoCount();
            if (i != LastAmmoCount)
            {
                LastAmmoCount = i;
                AmmoCountTF.SetText(i);
            }
        }
    else if (Weapon != LastWeapon || i <= LastAmmoCount)
    {
        AmmoCountTF.SetText("");
    }

    WeapKFZ = WepKFZ(KTP.Weapon);
    if (WeapKFZ != none)
    {
        if(WeapKFZ != LastWeapon)
        {
            MagTF.SetText("");
            r = (WeapKFZ.MagazineAmmoCountMax);
            LastWeapon = WeapKFZ;
        }
        r = WeapKFZ.GetMagCount();
            if(r != LastMag)
            {
                LastMag = r;
                magTF.SetText(r);
        }}
    else if (r <= LastMag || WeapKFZ != LastWeapon)
    {
        MagTF.SetText("");
    }


In my weapon:




var RepNotify int MagazineAmmoCount,MagazineAmmoCountMax;

replication
{
    // Server->Client properties
    if ( bNetDirty)
MagazineAmmoCount,MagazineAmmoCountMax;
}

simulated function bool HasAnyAmmo()
{
    return (( AmmoCount > 0 )||( MagazineAmmoCount > 0 ) || (ShotCost[0]==0 && ShotCost[1]==0));
}

simulated function int GetMagCount()
{
    return MagazineAmmoCount;
}

function ConsumeAmmo( byte FireModeNum )
{
   // Subtract the Ammo from the Magazine
   if(MagazineAmmoCount >= ShotCost[FireModeNum])
   {
      MagazineAmmoCount -= ShotCost[FireModeNum];
    AddAmmo(-ShotCost[FireModeNum]);
   }
}

simulated function bool HasAmmo( byte FireModeNum, optional int Amount )
{ 
   if (Amount == 0)
   {
      return (MagazineAmmoCount >= ShotCost[FireModeNum]);
   }
   else
   {
      return (MagazineAmmoCount >= Amount );
   }   
}

simulated function ReloadTheWeapon()
{
    local KFZPlayerController Controller;
    if (KFZPawn(Owner) != none)
    {
        Controller = KFZPlayerController(KFZPawn(Owner).Controller);
        CheckifbWasFullAmmo();

        if( Controller != none && MagazineAmmoCount == default.MagazineAmmoCount)
        {
            return;
        }
        else
        {
            bAiming = false;
            StopWeaponAnimation();
            PlayWeaponAnimation ( WeaponAimingOffAnim, AimingTime);
            bPressedReloadButton = true;
            GotoState('Reloading');
}}}


from state reloading...................

    function Reload()
    {
        local int TranferedAmmoCount;
        TranferedAmmoCount = Min(AmmoCount,MagazineAmmoCountMax - MagazineAmmoCount );

            if((AmmoCount > 0) && (TranferedAmmoCount > 0))
            {
                PlayWeaponAnimation(WeaponReload,ReloadTime);
                setTimer(ReloadTime,false,'ChargeMagazine');
                setTimer(ReloadTime,false,'EndOfReloading');
            }
            else
            {
                bReloading = false;
                GotoState('Active');
            }
    }

    simulated function ChargeMagazine()
    {
        local int TranferedAmmoCount;

        TranferedAmmoCount = Min(AmmoCount,MagazineAmmoCountMax - MagazineAmmoCount );
        MagazineAmmoCount += TranferedAmmoCount;
        AmmoCount -= TranferedAmmoCount;
    }


defaultprops

    MagazineAmmoCount = 50
    MagazineAmmoCountMax = 50
    AmmoCount = 600
    MaxAmmoCount = 650


Most of it is here. It shows the magazineAmmo code path. “Code Path” being that, following the path is the way I’ve got stuff working. I presume you have NotePad++ and UnCodeX which help follow where a piece of code goes.

Note fyi:
Extending from UT has been the most useful because whatever problems I’ve run up against, =>the UT coders have had similar problems and usually solved them.<=)

EG: my bots drop loot. Problem: the bot drops loot after being run over, but the dropped loot totals the vehicle or stops it dead. (loot is wallets, phones or similar.)

Rather than me messing with collision, I found a solution in Actor.uc:
/** Ignore Unreal collisions between PHYS_RigidBody pawns (vehicles/ragdolls) and this actor (only relevant if bIgnoreEncroachers is false) */
var bool bIgnoreRigidBodyPawns;

Solution: in my loot.uc defaultprops I placed:
bIgnoreEncroachers=false
bIgnoreRigidBodyPawns=false
Collision problems solved!

(except now the dropped loot sticks to the front of my vehicles… wip :slight_smile: )

Replicate the var AmmoTotal in the file its defined in.

Im just assuming if it like ours your reloading server side and the hud is client side ,so it needs replicating the var AmmoTotal does.

Hello my friend.

Thanks for repplying to my thread. Like I said, everything is working perfectly, whenever I collect Ammo, the pickup increases the AmmoTotal. And the ammo quantity count is manually transfered from AmmoTotal to Ammocount by the reloading function.

Just like I said, the only problem is Whenever the player reloads, the HUD which shows AmmoTotal updates normally. Whenever I collect ammo, it increases the AmmoTotal (my new variable), however, the display does not update the correct number, the number only updates whenever I shoot or whenever I reload.

So could you please explain to me in more details how can I replicate the var AmmoTotal? I am still a beginner in Unreal Script.

Thanks for the repply brother! :smiley: