using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;
using GTA;

namespace NomeScripts
{
    class SwingBat
    {
        int timeToCharge;
        int timeToSetOnFire;

        public void SetTiming(int chargeTime, int fireTime)
        {
            timeToCharge = chargeTime;
            timeToSetOnFire = chargeTime + fireTime;
        }

        /// <summary>
        /// Animation Style depending on what bike you are riding, just affects
        /// where the hands are for the handle bars during bat swing animation
        /// </summary>
        public enum AnimStyle
        {
            chopperStyle = 4,
            lowerStyle    = 3,
            fastStyle    = 2,
            normStyle    = 1,
            dirtStyle   = 0,
            Failed = -1
        }

        /// <summary>
        /// Constant string for the strike animation from the
        /// animation set missbike_combat
        /// </summary>
        const string batStrike = "_bat_attack_weak_";
        const string batPowerUpStrike = "_bat_attack_powerup_strike_";        
        const string batAttackIntro = "_bat_attack_intro_";
        const string batPowerAttackIntro = "_bat_attack_powerup_intro_";

        /// <summary>
        /// Constant to compare to inorder to check if a bike animation
        /// number acquisition has failed
        /// </summary>
        const int FAILEDMSG = (int)AnimStyle.Failed;        

        /// <summary>
        /// The animation set to swing the baseball bat whilst on a bike
        /// </summary>
        AnimationSet bikeCombat;

        /// <summary>
        /// The ped to swing the baseball bat from the bike.
        /// </summary>
        Ped ped;

        /// <summary>
        /// The bike lookup table which compares te bike name and returns
        /// its number which the bat swing animation must use
        /// </summary>
        KeyValuePair<string, AnimStyle>[] bikeLookup;

        /// <summary>
        /// Signifies whether the bat is swinging
        /// </summary>
        bool batIsSwinging;

        /// <summary>
        /// Signifies whether the ped is drawing the bat back
        /// </summary>
        bool drawingBatBack;

        /// <summary>
        /// Baseball bat object
        /// </summary>
        GTA.Object bat;

        /// <summary>
        /// A GTA Timer object to keep track of how long the swing button
        /// has been held (and whether it has been pressed). For increasing
        /// a swings strength.
        /// </summary>
        public GTA.Timer ChargerTimer { get { return chargerTimer; } }
        GTA.Timer chargerTimer;

        /// <summary>
        /// Current bike animation number
        /// </summary>
        int bikeAnimNum;

        /// <summary>
        /// Indicates the user is on a valid bike and the animations are ready
        /// Make false when the player leaves the bike
        /// </summary>
        public bool BikeReady { get { return bikeReady; } set { bikeReady = value; } }
        bool bikeReady;

        /// <summary>
        /// When the player has presses the swing left or swing right button this variable will be filled with "l" or "r"
        /// Upon letting go of the swings buttons it will be cleared
        /// </summary>
        String swing;

        /// <summary>
        /// A list of objects that have been hit and should not be hit agian during this swing event
        /// </summary>
        ArrayList dontHitAgain;

        /// <summary>
        /// Store the current anim playing
        /// </summary>
        string currentAnim = "";

        /// <summary>
        /// Bat strength, element one and two are the strengths against peds, elements
        /// 3 and 4 are strengths against vehicles.
        /// </summary>
        int[] BATSTRENGTHS = { 3, 6, 1, 3 };

        /// <summary>
        /// Keep track of PTFXs ids
        /// </summary>
        int fireEffectIDOne = -1;

        /// <summary>
        /// Depicts whether to use the time to calculate velocity or to use set figures
        /// </summary>
        public bool useSetStrength;

        /// <summary>
        /// Allows the cinimaic button to be disabled, set to false
        /// if another button configuration is used.
        /// </summary>
        public bool disableCiniAndHL;

        /// <summary>
        /// Determines whether wheb the bat is charged up you can set peds on fire
        /// </summary>
        public bool setPedsOnFire;

        /// <summary>
        /// Random Number generator to produce a random number when a decision is to be made
        /// </summary>
        Random randNumGen;

        /// <summary>
        /// Constructor. Accepts an array of KeyValuePair<string, AnimStyle>( Bike name, style).
        /// </summary>
        /// <param name="kvp">Array of KeyValuePair<string, AnimStyle>( Bike name, style)</param>
        public SwingBat(Ped pedToSwing)
        {
            bikeCombat = new AnimationSet("missbike_combat");
            ped = pedToSwing;
            bat = null;
            batIsSwinging = false;
            drawingBatBack = false;
            bikeReady = false;
            chargerTimer = new GTA.Timer();
            swing = "";
            dontHitAgain = new ArrayList();
            randNumGen = new Random();
            SetTiming(1500, 3500);
            bikeLookup = new KeyValuePair<string, AnimStyle>[] {// TLAD
                                                                new KeyValuePair<string, SwingBat.AnimStyle>("ANGEL", SwingBat.AnimStyle.normStyle),
                                                                new KeyValuePair<string, SwingBat.AnimStyle>("BATI", SwingBat.AnimStyle.fastStyle),
                                                                new KeyValuePair<string, SwingBat.AnimStyle>("DAEMON", SwingBat.AnimStyle.normStyle),
                                                                new KeyValuePair<string, SwingBat.AnimStyle>("DIABO", SwingBat.AnimStyle.chopperStyle),
                                                                new KeyValuePair<string, SwingBat.AnimStyle>("DOUBLE2", SwingBat.AnimStyle.fastStyle),
                                                                new KeyValuePair<string, SwingBat.AnimStyle>("HAKUCH", SwingBat.AnimStyle.fastStyle),
                                                                new KeyValuePair<string, SwingBat.AnimStyle>("HAKUCH2", SwingBat.AnimStyle.fastStyle),
                                                                new KeyValuePair<string, SwingBat.AnimStyle>("HEXER", SwingBat.AnimStyle.chopperStyle),
                                                                new KeyValuePair<string, SwingBat.AnimStyle>("INNOV", SwingBat.AnimStyle.chopperStyle),
                                                                new KeyValuePair<string, SwingBat.AnimStyle>("LYCAN", SwingBat.AnimStyle.chopperStyle),
                                                                new KeyValuePair<string, SwingBat.AnimStyle>("NIGHTBL", SwingBat.AnimStyle.chopperStyle),
                                                                new KeyValuePair<string, SwingBat.AnimStyle>("REVENANT", SwingBat.AnimStyle.chopperStyle),
                                                                new KeyValuePair<string, SwingBat.AnimStyle>("WAYFAR", SwingBat.AnimStyle.normStyle),
                                                                new KeyValuePair<string, SwingBat.AnimStyle>("WOLFS", SwingBat.AnimStyle.chopperStyle),

                                                                // TBOGT
                                                                new KeyValuePair<string, SwingBat.AnimStyle>("AKUMA", SwingBat.AnimStyle.fastStyle),
                                                                new KeyValuePair<string, SwingBat.AnimStyle>("BATI2", SwingBat.AnimStyle.fastStyle),
                                                                new KeyValuePair<string, SwingBat.AnimStyle>("DOUBLE", SwingBat.AnimStyle.fastStyle),
                                                                new KeyValuePair<string, SwingBat.AnimStyle>("POLICEB", SwingBat.AnimStyle.chopperStyle),
                                                                new KeyValuePair<string, SwingBat.AnimStyle>("VADER", SwingBat.AnimStyle.fastStyle),

                                                                // GTAIV
                                                                new KeyValuePair<string, SwingBat.AnimStyle>("BOBBER", SwingBat.AnimStyle.chopperStyle),
                                                                new KeyValuePair<string, SwingBat.AnimStyle>("FAGGIO", SwingBat.AnimStyle.lowerStyle),
                                                                new KeyValuePair<string, SwingBat.AnimStyle>("HELLFURY", SwingBat.AnimStyle.chopperStyle),
                                                                new KeyValuePair<string, SwingBat.AnimStyle>("NRG900", SwingBat.AnimStyle.fastStyle),
                                                                new KeyValuePair<string, SwingBat.AnimStyle>("PCJ", SwingBat.AnimStyle.fastStyle),
                                                                new KeyValuePair<string, SwingBat.AnimStyle>("SANCHEZ", SwingBat.AnimStyle.dirtStyle),
                                                                new KeyValuePair<string, SwingBat.AnimStyle>("ZOMB", SwingBat.AnimStyle.normStyle) };
        }

        /// <summary>
        /// Main update method of SwingBat, updates any changes
        /// in the state of swinging a bat
        /// </summary>
        public void Update(object sender, EventArgs e)
        {
            if (ped.CurrentVehicle != null)
            {
                // Check if the bike is not ready
                if (!BikeReady)
                {
                    pedGotOnBike();
                } else {
                    // Check the ped is the driver
                    if (ped == ped.CurrentVehicle.GetPedOnSeat(VehicleSeat.Driver))
                    {
                        disableCineAndHeadlightButton();
                        updateSwing();
                    }
                }
            } else if (bikeReady) {
                clearCompletely();
            }
        }

        /// <summary>
        /// Set up the correct bike animations when a ped is on a valid bike. Also disables
        /// the cinematic and headlight buttons.
        /// </summary>
        private void pedGotOnBike()
        {
            if (ped.CurrentVehicle.Model.isBike)
            {
                // Check ped is on bike and anim num is acquired
                bikeReady = getBikeAnims();

                if (bikeReady)
                {
                    disableCineAndHeadlightButton();
                }
            }
        }

        /// <summary>
        /// Updates the peds baseball bat swinging
        /// </summary>
        private void updateSwing()
        {
            // If the timer is running then the button is being held, play
            // and hold swing intro animation
            if (chargerTimer.isRunning && ped.isIdle &&
                !ped.Animation.isPlaying(bikeCombat, bikeAnimNum.ToString() + batStrike + swing))             
            {
                currentAnim = drawBackBat(swing, chargerTimer.ElapsedTime);
            }

            // Check we have a direction in swing and the timer is not running, as if
            // the timer is not running and we still have a swing direction 
            // that means the player has released the button.
            if ((swing == "l" || swing == "r") &&
                !chargerTimer.isRunning)
            {                
                currentAnim = releaseBat(swing, currentAnim);
                swing = swing.ToUpper();
            }

            // Whilst the bat is swinging, check if any pedestrians are within its reach
            if (batIsSwinging)
            {
                checkEntitiesAreWithinRange();
            }

            // When the swinging animation has completed, clean up
            if ((swing == "R" || swing == "L") &&
                ped.Animation.GetCurrentAnimationTime(bikeCombat, currentAnim) > 0.85F)
            {
                clearSwingData();
            }
        }

        /// <summary>
        /// Gets the correct bike swing bat anims, should be used
        /// when the player first gets on the bike
        /// </summary>
        /// <returns>Returns true if ped is on a valid bike</returns>
        private bool getBikeAnims()
        {
            if (ped.CurrentVehicle.Model.isBike &&
                ped.Weapons.Current.Type == Weapon.Melee_BaseballBat)
            {                
                // Check the players bike is in the lookup
                bikeAnimNum = checkBikeModel(ped.CurrentVehicle.Name);                
                
                if (bikeAnimNum == FAILEDMSG)
                {
                    Game.Console.Print("BikeNBat: Failed to find bike model in lookup table, unable to use anims");
                    return false;
                }

                return true;
            }

            return false;
        }

        /// <summary>
        /// Checks the lookup table has a key with the same modelName and returns
        /// its value. The value is for using the right animation for swinging the bat
        /// </summary>
        /// <param name="modelName">Model to check</param>
        /// <returns>Animation Number</returns>
        private int checkBikeModel(String modelName)
        {
            for (int i = 0; i < bikeLookup.Length; i++)
            {
                KeyValuePair<string, AnimStyle> kvp = bikeLookup[i];
                
                if (kvp.Key == modelName)
                {
                    return (int)kvp.Value;
                }
            }

            return FAILEDMSG;
        }

        /// <summary>
        /// The ped draws back the bat in stages, increasing the strength of the swing
        /// </summary>
        /// <param name="direction">The direction of the swing animation</param>
        /// <param name="timeElasped">Total time the button has been held</param>
        /// <returns>Animation name</returns>
        private string drawBackBat(string direction, int timeElasped)
        {
            string animName = bikeAnimNum.ToString() + batAttackIntro + direction;

            if (timeElasped < timeToCharge)
            {
                createBaseballBat(ped, direction);
                animName = bikeAnimNum.ToString() + batAttackIntro + direction;
            } else {
                animName = bikeAnimNum.ToString() + batPowerAttackIntro + direction;

                if (timeElasped > timeToSetOnFire &&
                    fireEffectIDOne == -1 &&
                    setPedsOnFire)
                {
                    // Start flame on the bat
                    fireEffectIDOne = GTA.Native.Function.Call<int>("START_PTFX_ON_OBJ", "fire_chopper_tail",
                                                                    bat,
                                                                    0.1F,
                                                                    direction == "l" ? 0.0F : 0.01F,
                                                                    0.5F,
                                                                    0.0F, 0.0F, 0.0F,
                                                                    0.15F);

                    // Make flame ignition sound                       
                    SoundEvents.PlayAudioEventFromObject("MOLOTOV_WOOF_NEAR1", bat);
                }
            }

            if (!ped.Animation.isPlaying(bikeCombat, animName) &&
                bat != null)
            {                
                drawingBatBack = true;
                ped.Task.PlayAnimation(bikeCombat, animName, 4.0F, AnimationFlags.Unknown06);
            }

            return animName;
        }

        /// <summary>
        /// Releases the bat swing
        /// </summary>
        /// <param name="direction">The direction of the swing animation</param>
        /// <returns>Striking animation name</returns>
        private string releaseBat(string direction, string anim)
        {
            string animName = "";

            if (anim.Contains(batPowerAttackIntro))
            {
                animName = bikeAnimNum.ToString() + batPowerUpStrike + direction;
            } else {
                animName = bikeAnimNum.ToString() + batStrike + direction;
            }

            if (!ped.Animation.isPlaying(bikeCombat, animName) &&
                drawingBatBack)
            {
                ped.Task.PlayAnimation(bikeCombat, animName, 4.0F);
                enableBatCollision();

                drawingBatBack = false;
                batIsSwinging = true;

                SoundEvents.PlayAudioEventFromObject("BASEBALLBAT_SWIPE", bat);
            }

            return animName;
        }

        /// <summary>
        /// Whilst the bat is swinging this continously checks
        /// whether a ped/vehicle is within reach and applies a velocity to it.
        /// </summary>
        private void checkEntitiesAreWithinRange()
        {
            // Calculate Left/Right vector of player depending on the swing
            GTA.Vector3 pedRightVec = getRightVector(ped.Direction);

            checkPedIsWithinSwingRange(pedRightVec);
            checkVehicleIsWithinRange(pedRightVec);
        }

        private void checkPedIsWithinSwingRange(GTA.Vector3 pedRightVec)
        {
            foreach (Ped hitPed in World.GetAllPeds())
            {
                if (hitPed != null &&                            // THe ped your hitting is valid
                    hitPed != ped &&                             // The ped your hitting is yourself
                    bat != null &&                               // The bat is valid
                    !dontHitAgain.Contains(hitPed) &&            // You havnt just hit it
                    hitPed.CurrentVehicle != ped.CurrentVehicle) // Not your own passenger
                {
                    // Allow peds to be attacked when they are on a bike
                    if (hitPed.CurrentVehicle != null)
                    {
                        if (!hitPed.CurrentVehicle.Model.isBike)
                        {
                            continue;
                        }
                    }

                    // Check the ped is in contact with the bat
                    if (hitPed.isTouching(bat))
                    {
                        dontHitAgain.Add(hitPed);
                        
                        // Handle what a ped should do when attacked
                        switch (randNumGen.Next(3))
                        {
                            case 0:
                                hitPed.Task.FightAgainst(ped);
                                break;
                            case 1:
                                hitPed.Task.HandsUp(2000);
                                break;
                            case 2:
                                hitPed.Task.FleeFromChar(ped);
                                break;
                            default:
                                break;
                        }

                        hitPed.Euphoria.BeingShot.Start(2000);

                        if (useSetStrength)
                        {
                            hitPed.Velocity += (swing == "L" ? pedRightVec *=-1 : pedRightVec) * (chargerTimer.ElapsedTime < timeToCharge ? BATSTRENGTHS[0] : BATSTRENGTHS[1]); // Apply Velocity
                            hitPed.Health -= (chargerTimer.ElapsedTime < timeToCharge ? BATSTRENGTHS[0] : BATSTRENGTHS[1]) * 12; // Damage Ped
                        } else {
                            hitPed.Velocity += (swing == "L" ? pedRightVec *= -1 : pedRightVec) * (chargerTimer.ElapsedTime / 200); // Apply Velocity
                            hitPed.Health -= chargerTimer.ElapsedTime / 20; // Damage Ped
                        }

                        // Only set someone on fire if the player has charged up enough
                        if (chargerTimer.ElapsedTime > timeToSetOnFire &&
                            setPedsOnFire)
                        {
                            GTA.Native.Function.Call("START_CHAR_FIRE", hitPed);
                        }

                        // Create blood ptfx
                        GTA.Native.Function.Call("TRIGGER_PTFX",
                                                    "blood_melee_blunt",
                                                    bat.Position.X,
                                                    bat.Position.Y,
                                                    bat.Position.Z,
                                                    0.0F,
                                                    0.0F,
                                                    0.0F,
                                                    1.0F);

                        // Make bat impact sound                        
                        SoundEvents.PlayAudioEventFromObject("BASEBALLBAT_TO_FACE", bat);

                        // Play react animation
                        //ped.Animation.Play(bikeCombat, bikeAnimNum.ToString() + "_hit_react_" + swing.ToLower(), 1.0F, AnimationFlags.Unknown06);
                    }
                }
            }
        }

        private void checkVehicleIsWithinRange(GTA.Vector3 pedRightVec)
        {
            foreach (Vehicle hitVeh in World.GetAllVehicles())
            {
                if (hitVeh != null &&                // Vehicle your hitting is valid
                    hitVeh != ped.CurrentVehicle &&  // Vehicle hit is not your own
                    bat != null &&                   // The bat is valid
                    !dontHitAgain.Contains(hitVeh))  // You havn't just hit it
                {
                    if (GTA.Native.Function.Call<bool>("IS_VEHICLE_TOUCHING_OBJECT", hitVeh, bat))
                    {
                        dontHitAgain.Add(hitVeh);

                        if (useSetStrength)
                        {
                            hitVeh.Velocity += (swing == "L" ? pedRightVec *= -1 : pedRightVec) * (chargerTimer.ElapsedTime < timeToCharge ? BATSTRENGTHS[2] : BATSTRENGTHS[3]); // Apply Velocity
                            hitVeh.EngineHealth -= (chargerTimer.ElapsedTime < timeToCharge ? BATSTRENGTHS[2] * 10 : BATSTRENGTHS[3]) * 10; // Damage Vehicle
                        } else {
                            hitVeh.Velocity += (swing == "L" ? pedRightVec *= -1 : pedRightVec) * (chargerTimer.ElapsedTime / 200); // Apply Velocity
                            hitVeh.EngineHealth -= chargerTimer.ElapsedTime / 10; // Damage Vehicle
                        }

                        // Create spark ptfx
                        GTA.Native.Function.Call("TRIGGER_PTFX",
                                                    "break_sparks",
                                                    bat.Position.X,
                                                    bat.Position.Y,
                                                    bat.Position.Z,
                                                    0.0F,
                                                    0.0F,
                                                    0.0F,
                                                    1.0F);

                        // Make bat impact sound
                        SoundEvents.PlayAudioEventFromVehicle("COLLISIONS_COLLISIONS_HOLLOW_METAL_PANEL_2_1", hitVeh);

                        // Choose what to damage
                        switch (randNumGen.Next(4))
                        {
                            case 0:
                                GTA.Native.Function.Call("SMASH_CAR_WINDOW", hitVeh, randNumGen.Next(7));
                                break;
                            case 1:
                                GTA.Native.Function.Call("OPEN_CAR_DOOR", hitVeh, randNumGen.Next(6));
                                break;
                            case 2:
                                GTA.Native.Function.Call("BREAK_CAR_DOOR", hitVeh, randNumGen.Next(6), true);
                                break;
                            case 3:
                                // Do nothing
                                break;
                            default:
                                break;
                        }

                        if (randNumGen.Next(3) > 1)
                        {
                            Ped driver = hitVeh.GetPedOnSeat(VehicleSeat.Driver);

                            if (driver != null)
                            {
                                if (driver.Exists())
                                {
                                    driver.WillUseCarsInCombat = true;
                                    driver.ChangeRelationship(RelationshipGroup.Player, Relationship.Hate);
                                    driver.FleeByVehicle(hitVeh);
                                }
                            }
                        }

                        // Play react animation
                        //ped.Animation.Play(bikeCombat, bikeAnimNum.ToString() + "_hit_react_" + swing.ToLower(), 1.0F, AnimationFlags.Unknown06);
                    }
                }
            }
        }

        /// <summary>
        /// Creates a baseball bat in the hand of the ped passed to this method. A direction is required in the
        /// form of a string as "l" or "r".
        /// </summary>
        /// <param name="attachObjToPed">Ped to get baseballbat</param>
        /// <param name="direction">String direction, "l" or "r"</param>
        private void createBaseballBat(Ped attachObjToPed, string direction)
        {
            if (bat != null)
            {
                if (bat.Exists()) return;
            }

            Bone hand;
            GTA.Vector3 batRot;
            GTA.Vector3 batPos;

            if (direction == "l")
            {
                batPos = new GTA.Vector3(-0.02F, -0.015F, 0.0F);
                batRot = new GTA.Vector3(3.0F, -0.3F, 0.5F);
                hand = Bone.LeftHand;
            } else {
                batPos = new GTA.Vector3(-0.015F, -0.015F, 0.0F);
                batRot = new GTA.Vector3(0.0F, 0.3F, 0.0F);
                hand = Bone.RightHand;
            }

            try
            {
                bat = World.CreateObject("w_bat", attachObjToPed.Position);
                bat.AttachToPed(attachObjToPed, hand, batPos, batRot);
            } catch (NullReferenceException) {
                // Just catch it
            }
        }

        /// <summary>
        /// Delete the bat object.
        /// </summary>
        private void deleteBat()
        {
            if (bat != null)
            {
                if (bat.Exists())
                {
                    bat.Delete();
                    bat = null;
                }
            }
        }

        /// <summary>
        /// Enables the baseball bat to have collision.
        /// </summary>
        private void enableBatCollision()
        {
            if (bat != null)
            {
                if (bat.Exists())
                {
                    bat.Collision = true;
                }
            }
        }

        /// <summary>
        /// To be used for when the player hasnt completed a swing, this maybe caused by falling off the bike
        /// </summary>
        private void clearSwingData()
        {
            currentAnim = "";
            dontHitAgain.Clear();
            deleteBat();
            batIsSwinging = false;
            drawingBatBack = false;
            ped.BlockGestures = false;
            ped.BlockPermanentEvents = false;
            swing = "";
            GTA.Native.Function.Call("STOP_PTFX", fireEffectIDOne);
            fireEffectIDOne = -1;
        }

        /// <summary>
        /// Completely reset any changes this class has made
        /// </summary>
        private void clearCompletely()
        {
            clearSwingData();

            bikeReady = false;
            chargerTimer.Stop();

            if (!disableCiniAndHL)
            {
                // Enable Headlight and Cinematic button
                GTA.Native.Function.Call("SET_CINEMATIC_BUTTON_ENABLED", 1);

                // Check we are on the one of the episodes, as this native function is not available on gta4
                if (GameEpisode.TLAD == Game.CurrentEpisode ||
                    GameEpisode.TBOGT == Game.CurrentEpisode)
                {
                    GTA.Native.Function.Call("SET_SUPPRESS_HEADLIGHT_SWITCH", 0);
                }
            }
        }

        /// <summary>
        /// Disable the headlight and cinematic button as not to
        /// interfere if those buttons are used for the swing event
        /// </summary>
        private void disableCineAndHeadlightButton()
        {
            if (disableCiniAndHL)
            {
                // Disable Headlight and Cinematic button
                GTA.Native.Function.Call("SET_CINEMATIC_BUTTON_ENABLED", 0);

                // Check we are on the one of the episodes, as this native function is not available on gta4
                if (GameEpisode.TLAD == Game.CurrentEpisode ||
                    GameEpisode.TBOGT == Game.CurrentEpisode)
                {
                    GTA.Native.Function.Call("SET_SUPPRESS_HEADLIGHT_SWITCH", 1);
                }
            }
        }

        /// <summary>
        /// Indicate to swing the bat left
        /// </summary>
        public void SwingLeft()
        {
            if (ped.CurrentVehicle != null)
            {
                if (bikeReady &&
                    !drawingBatBack &&
                    !chargerTimer.isRunning &&
                    !batIsSwinging &&
                    ped == ped.CurrentVehicle.GetPedOnSeat(VehicleSeat.Driver))
                {
                    chargerTimer.Start();
                    swing = "l";
                }
            }
        }

        /// <summary>
        /// Indicate to swing the bat right
        /// </summary>
        public void SwingRight()
        {
            if (ped.CurrentVehicle != null)
            {
                if (bikeReady &&
                    !drawingBatBack &&
                    !chargerTimer.isRunning &&
                    !batIsSwinging &&
                    ped == ped.CurrentVehicle.GetPedOnSeat(VehicleSeat.Driver))
                {
                    chargerTimer.Start();
                    swing = "r";
                }
            }
        }

        /// <summary>
        /// Returns the right vector of a given forward vector.
        /// Negate this return value for the left vector
        /// </summary>
        /// <param name="forward"></param>
        /// <returns></returns>
        private GTA.Vector3 getRightVector(GTA.Vector3 forward)
        {
            // Get the right Vector
            return getRightVector(forward, new GTA.Vector3(0, 0, -1));
        }

        /// <summary>
        /// Returns the right vector of a given forward and up vectors.
        /// Negate this return value for the left vector
        /// </summary>
        /// <param name="forward">Forward Vector</param>
        /// <param name="up">Up Vector</param>
        /// <returns>Right Vector</returns>
        private GTA.Vector3 getRightVector(GTA.Vector3 forward, GTA.Vector3 up)
        {
            // Get the right Vector of the camera
            up.Normalize();
            forward.Normalize();
            GTA.Vector3 right = GTA.Vector3.Cross(up, forward);
            right.Normalize();
            return right;
        }
    }
}
