Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System.Collections.Generic;
- using System.Threading.Tasks;
- using CitizenFX.Core;
- using CitizenFX.Core.Native;
- namespace Afterburners
- {
- public class Afterburners : BaseScript
- {
- /// <summary>
- /// Player vehicle
- /// </summary>
- private readonly Dictionary<int, PlayerScriptData> m_players = new Dictionary<int, PlayerScriptData>();
- /// <summary>
- /// Initialize the script
- /// </summary>
- public Afterburners()
- {
- Tick += OnTick;
- }
- /// <summary>
- /// Tick event
- /// </summary>
- private async Task OnTick()
- {
- foreach (var playerIdx in Players)
- {
- var player = playerIdx.Character;
- if (!m_players.ContainsKey(playerIdx.Handle))
- {
- m_players.Add(playerIdx.Handle, new PlayerScriptData());
- }
- await m_players[playerIdx.Handle].Run(player);
- }
- }
- private class PlayerScriptData
- {
- private PlayerVehicle m_mainVehicle;
- public async Task Run(Ped player)
- {
- if ((m_mainVehicle != null) && !player.IsInVehicle(m_mainVehicle.Vehicle))
- {
- m_mainVehicle.KillAfterburner();
- m_mainVehicle = default(PlayerVehicle);
- }
- if (player.IsInVehicle())
- {
- if ((m_mainVehicle != null) && player.CurrentVehicle.IsDriveable)
- {
- m_mainVehicle.Update();
- }
- foreach (var vehicle in Vehicles)
- {
- if ((player.CurrentVehicle.Model == vehicle) && ((m_mainVehicle == null) || (m_mainVehicle.Handle != player.CurrentVehicle.Handle)))
- {
- m_mainVehicle = new PlayerVehicle(player.CurrentVehicle);
- await m_mainVehicle.InitializeAfterburner();
- }
- }
- }
- }
- }
- #region Constant Vars
- /// <summary>
- /// Scale of afterburners.
- /// </summary>
- public static readonly float Scale = 0.1f;
- /// <summary>
- /// Left afterburner relative offset.
- /// </summary>
- public static readonly Vector3 LeftOffset = new Vector3(-0.0f, -0f, 0.0f);
- /// <summary>
- /// Right afterburner relative offset.
- /// </summary>
- public static readonly Vector3 RightOffset = new Vector3(0.0f, -0f, 0.0f);
- /// <summary>
- /// Vehicles with afterburner support.
- /// </summary>
- public static readonly VehicleHash[] Vehicles =
- {
- (VehicleHash)0xF93D230C, // yMetalSlugA
- (VehicleHash)0x0CC34A18, // yMetalSlugB
- };
- #endregion
- }
- public class PlayerVehicle : Entity
- {
- private readonly LoopedPtfx m_afterburnerL = new LoopedPtfx("core", "veh_exhaust_afterburner");
- private readonly LoopedPtfx m_afterburnerR = new LoopedPtfx("core", "veh_exhaust_afterburner");
- /// <summary>
- /// Initialize the class
- /// </summary>
- /// <param name="vehicle"></param>
- public PlayerVehicle(Vehicle vehicle) : base(vehicle.Handle)
- {
- Vehicle = vehicle;
- }
- public Vehicle Vehicle { get; }
- /// <summary>
- /// Initialize afterburners on entitys exhaust dummies
- /// </summary>
- public async Task InitializeAfterburner()
- {
- if (!m_afterburnerL.IsLoaded)
- {
- await m_afterburnerL.Load();
- }
- m_afterburnerL.Start(Vehicle, Afterburners.Scale, Afterburners.LeftOffset, Vector3.Zero, (Bone)Function.Call<int>(Hash.GET_ENTITY_BONE_INDEX_BY_NAME, Vehicle, "exhaust"));
- m_afterburnerR.Start(Vehicle, Afterburners.Scale, Afterburners.RightOffset, Vector3.Zero, (Bone)Function.Call<int>(Hash.GET_ENTITY_BONE_INDEX_BY_NAME, Vehicle, "exhaust_2"));
- Function.Call((Hash)0xDCB194B85EF7B541, m_afterburnerL.Handle, 3000.0f);
- Function.Call((Hash)0xDCB194B85EF7B541, m_afterburnerR.Handle, 3000.0f);
- }
- /// <summary>
- /// Kill the afterburner FX
- /// </summary>
- public void KillAfterburner()
- {
- m_afterburnerL.Remove();
- m_afterburnerR.Remove();
- }
- /// <summary>
- /// Update FX based on acceleration
- /// </summary>
- public void Update()
- {
- Function.Call(Hash.SET_PARTICLE_FX_LOOPED_EVOLUTION, m_afterburnerL.Handle, "throttle", Vehicle.Acceleration, 0);
- Function.Call(Hash.SET_PARTICLE_FX_LOOPED_EVOLUTION, m_afterburnerR.Handle, "throttle", Vehicle.Acceleration, 0);
- }
- }
- public class LoopedPtfx
- {
- /// <summary>
- /// Initialize the class
- /// </summary>
- /// <param name="assetName"></param>
- /// <param name="fxName"></param>
- public LoopedPtfx(string assetName, string fxName)
- {
- Handle = -1;
- AssetName = assetName;
- FxName = fxName;
- }
- public int Handle { get; private set; }
- public string AssetName { get; }
- public string FxName { get; }
- /// <summary>
- /// If the particle FX is spawned.
- /// </summary>
- public bool Exists
- {
- get
- {
- if (Handle == -1)
- {
- return false;
- }
- return Function.Call<bool>(Hash.DOES_PARTICLE_FX_LOOPED_EXIST, Handle);
- }
- }
- /// <summary>
- /// If the particle FX asset is loaded.
- /// </summary>
- public bool IsLoaded => Function.Call<bool>(Hash.HAS_NAMED_PTFX_ASSET_LOADED, AssetName);
- /// <summary>
- /// Load the particle FX asset
- /// </summary>
- public async Task Load()
- {
- Function.Call(Hash.REQUEST_NAMED_PTFX_ASSET, AssetName);
- while (!Function.Call<bool>(Hash.HAS_NAMED_PTFX_ASSET_LOADED))
- {
- await BaseScript.Delay(0);
- }
- }
- /// <summary>
- /// Start particle FX on the specified entity.
- /// </summary>
- /// <param name="entity">Entity to attach to.</param>
- /// <param name="scale">Scale of the fx.</param>
- /// <param name="offset">Optional offset.</param>
- /// <param name="rotation">Optional rotation.</param>
- /// <param name="bone">Entity bone.</param>
- public void Start(Entity entity, float scale, Vector3 offset, Vector3 rotation, Bone? bone)
- {
- if (Handle != -1)
- {
- return;
- }
- Function.Call(Hash._SET_PTFX_ASSET_NEXT_CALL, AssetName);
- Handle = bone == null
- ? Function.Call<int>(
- Hash.START_PARTICLE_FX_LOOPED_ON_ENTITY,
- FxName,
- entity,
- offset.X,
- offset.Y,
- offset.Z,
- rotation.X,
- rotation.Y,
- rotation.Z,
- scale,
- 0,
- 0,
- 1)
- : Function.Call<int>(
- Hash._START_PARTICLE_FX_LOOPED_ON_ENTITY_BONE,
- FxName,
- entity,
- offset.X,
- offset.Y,
- offset.Z,
- rotation.X,
- rotation.Y,
- rotation.Z,
- (int)bone,
- scale,
- 0,
- 0,
- 0);
- }
- /// <summary>
- /// Start particle FX on the specified entity.
- /// </summary>
- /// <param name="entity">Entity to attach to.</param>
- /// <param name="scale">Scale of the fx.</param>
- public void Start(Entity entity, float scale)
- {
- Start(entity, scale, Vector3.Zero, Vector3.Zero, null);
- }
- /// <summary>
- /// Start particle FX at the specified position.
- /// </summary>
- /// <param name="position">Position in world space.</param>
- /// <param name="scale">Scale of the fx.</param>
- /// <param name="rotation">Optional rotation.</param>
- public void Start(Vector3 position, float scale, Vector3 rotation)
- {
- if (Handle != -1)
- {
- return;
- }
- Function.Call(Hash._SET_PTFX_ASSET_NEXT_CALL, AssetName);
- Handle = Function.Call<int>(
- Hash.START_PARTICLE_FX_LOOPED_AT_COORD,
- FxName,
- position.X,
- position.Y,
- position.Z,
- rotation.X,
- rotation.Y,
- rotation.Z,
- scale,
- 0,
- 0,
- 0,
- 0);
- }
- /// <summary>
- /// Start particle FX at the specified position.
- /// </summary>
- /// <param name="position">Position in world space.</param>
- /// <param name="scale">Scale of the fx.</param>
- public void Start(Vector3 position, float scale)
- {
- Start(position, scale, Vector3.Zero);
- }
- /// <summary>
- /// Remove the particle FX
- /// </summary>
- public void Remove()
- {
- if (Handle == -1)
- {
- return;
- }
- Function.Call(Hash.REMOVE_PARTICLE_FX, Handle, 0);
- Handle = -1;
- }
- /// <summary>
- /// Remove the particle FX in range
- /// </summary>
- public void Remove(Vector3 position, float radius)
- {
- if (Handle == -1)
- {
- return;
- }
- Function.Call(Hash.REMOVE_PARTICLE_FX_IN_RANGE, position.X, position.Y, position.Z, radius);
- Handle = -1;
- }
- /// <summary>
- /// Unload the loaded particle FX asset
- /// </summary>
- public void Unload()
- {
- if (IsLoaded)
- {
- Function.Call((Hash)0x5F61EBBE1A00F96D, AssetName);
- }
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement