news about forums links tools tutorials contact

Flamethrower - author: c0mpi1e
    //================================================
    // FireBitch.
    // Same as GasBagBelch only has a shorter life-time - serves as the flame
    //================================================

    class FireBitch expands GasBagBelch;
Here we go! The Firebitch is a subclassed GasBagBelch - it is the projectile you get when firing the FlameThrower. Ok, as you know the PostBeginPlay function/event (both the same in Unreal) is called directly before the object is spawned in the level.
    function PostBeginPlay()
    {
      if ( ScriptedPawn(Instigator) != None )
        Speed = ScriptedPawn(Instigator).ProjectileSpeed / 2;
      PlaySound(SpawnSound);
      Velocity = Vector(Rotation) * speed;
      MakeNoise ( 1.0 );
      Texture = SpriteAnim[0];
      i=1;
      SetTimer(0.15,True);
      Super.PostBeginPlay();
    }
This essentially slows down the GasBagBelch by half i.e. the slash 2. Ok, now we kick into the Flying state. This occurs when the projectile is spawned.
    auto state Flying
    {
HitWall believe it or not, is called when the object smacks into a solid object in Unreal, which isn't a pawn or similar.
      simulated function HitWall( vector HitNormal, actor Wall )
      {

        // For a cool effect if the smoke hits the wall
        // or the floor then start a smoke puff that keeps
        // going for a while

        if (Frand() > 0.6)
        {
          spawn(class'ShortSmokeGen',,,Location+HitNormal * 9);
          Destroy();
        }
      }
Process Touch occurs when the object hits an actor. It passes the reference to the actor, and the vector (3d coords) of where the firebitch hit. Notice that if the player who created the FireBitch is the one who gets hit, then no damage occurs. Otherwise, the TakeDamage function of the other actor is called to take burn damage.
      function ProcessTouch (Actor Other, Vector HitLocation)
      {
        if (Other != instigator)
        {
          // Change from just regular Damage
          Other.TakeDamage(Damage/2, instigator,HitLocation,
              15000.0 * Normal(velocity), 'burned');

          ExplodeCheck(HitLocation, Vect(0,0,0), 1);
        }
      }
ExplodeCheck checks whether or not the FireBitch should produce an explosion effect. If the shottype is 0, then call the explode function. Theres a fifty-fifty chance then of creating a flame explosion effect.
      function ExplodeCheck(vector HitLocation, vector HitNormal, int shottype)
      {
        if (shottype == 0)
          {
            Explode(HitLocation, Vect(0, 0, 0));
            return;
          }
        if (FRand() < 0.5)
          MakeNoise(0.1);
        spawn(class'FlameExplosion',,,HitLocation+HitNormal * 9);
        Destroy();
      }
Explode is called when the firebitch has been determined to explode. If it does explode, make a noise.
      function Explode(vector HitLocation, vector HitNormal)
      {
        if (FRand() < 0.5)
          MakeNoise(0.1); //FIXME - set appropriate loudness
        Destroy();
      }
The begin label is where the actual code starts after the Post event. It lives for 0.9 seconds before calling ExplodeCheck to determine whether it should stop. For example, if you wanted the FireBitch to last for 2 secs, then input Sleep( 2.0 ).
    Begin:
      // Changed from 3 to 0.3
      Sleep(0.9);
      ExplodeCheck(Location, Vect(0,0,0), 0);

    }

    //===============================================
    // FlameThrower.
    // ==============
    // created by c0mpi1e
    // create a flame thrower using the gasbagbelch projectile
    //
    // Advantages:
    // ++++very very deadly at close range
    // Disadvantages:
    // ++++only a close range weapon, and when shot reduces visiblity
    //
    //===============================================

    class FlameThrower expands GESBioRifle;
The EXEC command loads in game experience data (audio, visual, mesh, etc). In this case, it loads in a flame sound created by c0mpi1e, and names it 'flame'. This sound can then be called by the PlaySound function.
    #exec AUDIO IMPORT FILE="Sounds'TornSounds.flame.wav'" NAME="flame"
        GROUP="FlameThrower"

    var() int length;
    var() Projectile Gel;
    var() int i;
Again, this is called when the object spawns. It basically changes the class that it fires to FireBitch rather than GasBagBelch.
    function PreBeginPlay()
    {
      length = 0;
      i = 0;
      Super.PreBeginPlay();

      ProjectileClass = class'FireBitch';
      ProjectileSpeed = class'FireBitch'.default.speed;
      AltProjectileClass = class'FireBitch';
      AltProjectileSpeed = class'FireBitch'.default.speed;
    }
When the user hits primary fire, this code takes place. It calculates where the player is, adjusts the aim to take into account of the projectile, and then files a FireBitch.
    function Projectile ProjectileFire(class ProjClass, float ProjSpeed, bool bWarn)
    {
      local Vector Start, X,Y,Z;
      Owner.MakeNoise(Pawn(Owner).SoundDampening);
      GetAxes(Pawn(owner).ViewRotation,X,Y,Z);
      Start = Owner.Location + CalcDrawOffset() + FireOffset.X * X
              + FireOffset.Y * Y + FireOffset.Z * Z;
      AdjustedAim = pawn(owner).AdjustToss(ProjSpeed, Start, 0,
                         True, (bWarn || (FRand() < 0.4)));
      return Spawn(ProjClass,,, Start,AdjustedAim);
    }
Alternate fire.
    function AltFire( float Value )
    {

      bPointing=True;
      if ( AmmoType.AmmoAmount != 0 )
      {

        CheckVisibility();
        GoToState('AltFiring');
      }
      else
        GoToState('Idle');
    }
Both Normal and Altfire modes are the same, so just make Fire point to the altfire code.
    function Fire( float Value )
    {
      bPointing=True;
      if ( AmmoType.AmmoAmount != 0 )
      {
        CheckVisibility();
        GoToState('AltFiring');
      }
      else
        GoToState('Idle');
    }
We would like to overide the alt firing function because we are inheriting from the bio rifle, and it charges for its alt fire. We would like to keep shooting as long as the button is pressed down and the ammo is not used up there fore just call shoot load which will handle everything.
    state AltFiring
    {
      function Tick( float DeltaTime )
      {
      }

    Begin:
      GotoState('ShootLoad');
      Finish();
    }

    state ShootLoad
    {
      function Fire(float F) {}
      function AltFire(float F) {}
      function BeginState()
      {
        Super.BeginState();
      }
    Begin:

      // Ok, shoot a projectile 10 times for every shot
      // makes the streaming more fluid because we force
      // the shot to shoot 10 times, so no matter what the
      // rendering speed 10 shots will be shot.
      // FIXME--fix that damn rendering problem, i have a
      // --suspicion that a timer would help but I'm sick of
      // --this thing already

      while (i < 10)
      {
        // Because we take command of shooting away from
        // function AltFire we have to control the ammo here

        if (AmmoType.AmmoAmount != 0)
        {
          // Call the shooting function

          Gel = ProjectileFire(AltProjectileClass, AltProjectileSpeed, bAltWarnTarget);

          // And set the drawscale to make the baggasbelch larger
          Gel.DrawScale = 4;

          // Then play the flame sound
          Owner.PlaySound(FireSound, SLOT_Misc,
    1.7*Pawn(Owner).SoundDampening,,,fMax(0.5,1.35-ChargeSize/8.0) );  //shoot goop

          // For every fifth shot fired take off ammo
          // you could also say if i == 5 but this
          // way you can change the while condition
          if (i % 5 == 0)
            AmmoType.UseAmmo(1);

          // For effect if ammo is under 15 then weeze out the shots
          if (AmmoType.AmmoAmount < 15)
            if (FRand() > 0.8)
              {
                FinishAnim();
                break;
              }

          // Pause a sec so the shots don't all come out at once
          Sleep(0);
          i++;
        }
      }

      // Play gun firing anim.
      PlayAnim('Fire',0.4, 0.05);

      i = 0;
      Finish();
    }